mimi-seed 0.6.0 → 0.7.0
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/{chunk-R3LS4FY2.js → chunk-47TS72IP.js} +287 -378
- package/dist/{chunk-DW3LOLPJ.js → chunk-QU2IDWJ2.js} +8 -1
- package/dist/chunk-SZQFVTEW.js +252 -0
- package/dist/index.js +895 -332
- package/dist/{mcp-client-SLIKR42C.js → mcp-client-PVWDCYJN.js} +2 -1
- package/dist/{setup-G2JY35UW.js → setup-NQHLA3AJ.js} +2 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
mcpCall
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QU2IDWJ2.js";
|
|
5
5
|
import {
|
|
6
6
|
CONFIG_LOCATION,
|
|
7
7
|
CREDENTIALS,
|
|
@@ -15,16 +15,19 @@ import {
|
|
|
15
15
|
detectHints,
|
|
16
16
|
getEffectiveConfig,
|
|
17
17
|
hasAnyProjectSignal,
|
|
18
|
-
isLang,
|
|
19
18
|
isSatisfied,
|
|
20
19
|
migrateLegacyJenkins,
|
|
21
|
-
resolveLang,
|
|
22
20
|
runMcpBin,
|
|
23
|
-
t,
|
|
24
21
|
tryCredById,
|
|
25
|
-
writeConfig
|
|
22
|
+
writeConfig
|
|
23
|
+
} from "./chunk-47TS72IP.js";
|
|
24
|
+
import {
|
|
25
|
+
catalog,
|
|
26
|
+
isLang,
|
|
27
|
+
resolveLang,
|
|
28
|
+
t,
|
|
26
29
|
writeSettings
|
|
27
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-SZQFVTEW.js";
|
|
28
31
|
|
|
29
32
|
// src/index.ts
|
|
30
33
|
import os3 from "os";
|
|
@@ -35,6 +38,20 @@ import open from "open";
|
|
|
35
38
|
|
|
36
39
|
// src/handshake.ts
|
|
37
40
|
import http from "http";
|
|
41
|
+
var M = catalog(
|
|
42
|
+
{
|
|
43
|
+
htmlLang: "ko",
|
|
44
|
+
connected: "\u2713 Mimi Seed \uC5F0\uACB0 \uC644\uB8CC",
|
|
45
|
+
backToTerminal: "\uD130\uBBF8\uB110\uB85C \uB3CC\uC544\uAC00\uC138\uC694.",
|
|
46
|
+
timeout: (seconds) => `${seconds}\uCD08 \uC548\uC5D0 \uC5F0\uACB0\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
htmlLang: "en",
|
|
50
|
+
connected: "\u2713 Mimi Seed connected",
|
|
51
|
+
backToTerminal: "You can go back to your terminal.",
|
|
52
|
+
timeout: (seconds) => `Not connected within ${seconds}s.`
|
|
53
|
+
}
|
|
54
|
+
);
|
|
38
55
|
async function awaitHandshake(timeoutMs) {
|
|
39
56
|
let resolve;
|
|
40
57
|
let reject;
|
|
@@ -63,9 +80,9 @@ async function awaitHandshake(timeoutMs) {
|
|
|
63
80
|
}
|
|
64
81
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
65
82
|
res.end(`<!doctype html>
|
|
66
|
-
<html lang="
|
|
67
|
-
<h2
|
|
68
|
-
<p
|
|
83
|
+
<html lang="${M().htmlLang}"><body style="font-family:system-ui;padding:40px;max-width:480px;margin:auto">
|
|
84
|
+
<h2>${M().connected}</h2>
|
|
85
|
+
<p>${M().backToTerminal}</p>
|
|
69
86
|
<script>setTimeout(()=>window.close(),1000)</script>
|
|
70
87
|
</body></html>`);
|
|
71
88
|
resolve({ token, prefix });
|
|
@@ -76,7 +93,7 @@ async function awaitHandshake(timeoutMs) {
|
|
|
76
93
|
const port = server.address().port;
|
|
77
94
|
const timer = setTimeout(() => {
|
|
78
95
|
server.close();
|
|
79
|
-
reject(new Error(
|
|
96
|
+
reject(new Error(M().timeout(timeoutMs / 1e3)));
|
|
80
97
|
}, timeoutMs);
|
|
81
98
|
promise.finally(() => clearTimeout(timer));
|
|
82
99
|
return { port, promise };
|
|
@@ -267,6 +284,70 @@ async function cmdDoctor() {
|
|
|
267
284
|
|
|
268
285
|
// src/check.ts
|
|
269
286
|
import kleur2 from "kleur";
|
|
287
|
+
var M2 = catalog(
|
|
288
|
+
{
|
|
289
|
+
noAccount: "\uC5F0\uACB0\uB41C \uACC4\uC815 \uC5C6\uC74C. `mimi-seed init` \uC2E4\uD589.\n",
|
|
290
|
+
title: "mimi-seed check \u2014 \uCD9C\uC2DC \uC804 \uC810\uAC80\n\n",
|
|
291
|
+
appsFailed: (msg) => `\uC571 \uBAA9\uB85D \uC870\uD68C \uC2E4\uD328: ${msg}
|
|
292
|
+
`,
|
|
293
|
+
noApps: "\uB4F1\uB85D\uB41C \uC571\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. `mimi-seed init` \uD6C4 \uC571\uC744 \uB4F1\uB85D\uD558\uC138\uC694.\n",
|
|
294
|
+
app: (name) => `\uC571: ${name}
|
|
295
|
+
|
|
296
|
+
`,
|
|
297
|
+
appsParseFailed: (raw) => `\uC571 \uBAA9\uB85D \uD30C\uC2F1 \uC2E4\uD328: ${raw}
|
|
298
|
+
`,
|
|
299
|
+
scoring: "\u{1F4CA} Readiness \uC810\uC218 \uACC4\uC0B0 \uC911...\n",
|
|
300
|
+
scoreFailed: (msg) => `\uC810\uC218 \uC870\uD68C \uC2E4\uD328: ${msg}
|
|
301
|
+
`,
|
|
302
|
+
score: (bar) => `
|
|
303
|
+
\uC810\uC218: ${bar}
|
|
304
|
+
|
|
305
|
+
`,
|
|
306
|
+
byModule: "\u2500\u2500 \uBAA8\uB4C8\uBCC4 \u2500\u2500\n",
|
|
307
|
+
blockers: "\u{1F6AB} \uBE14\uB85C\uCEE4:\n",
|
|
308
|
+
warnings: "\u26A0 \uACBD\uACE0:\n",
|
|
309
|
+
stepIntegration: (url) => `\uC5F0\uACB0 \uC9C4\uB2E8 ${url}`,
|
|
310
|
+
stepCopy: (url) => `\uBB38\uAD6C \uBCF4\uAC15 mimi-seed notes \uB610\uB294 ${url}`,
|
|
311
|
+
stepScreenshot: (url) => `\uC2A4\uD06C\uB9B0\uC0F7 ${url}`,
|
|
312
|
+
stepChecklist: (url) => `\uCCB4\uD06C\uB9AC\uC2A4\uD2B8 ${url}`,
|
|
313
|
+
nextSteps: "\u2192 \uB2E4\uC74C \uB2E8\uACC4:\n",
|
|
314
|
+
preview: " \uBBF8\uB9AC\uBCF4\uAE30: mimi-seed deploy --dry-run\n\n",
|
|
315
|
+
ready: "\u2713 \uCD9C\uC2DC \uC900\uBE44 \uC644\uB8CC!\n",
|
|
316
|
+
notReady: (score) => `\uC544\uC9C1 ${score}/100 \u2014 \uC704 \uB2E4\uC74C \uB2E8\uACC4\uB97C \uC9C4\uD589\uD558\uC138\uC694.
|
|
317
|
+
`
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
noAccount: "No account connected. Run `mimi-seed init`.\n",
|
|
321
|
+
title: "mimi-seed check \u2014 pre-launch check\n\n",
|
|
322
|
+
appsFailed: (msg) => `Failed to list apps: ${msg}
|
|
323
|
+
`,
|
|
324
|
+
noApps: "No apps registered. Run `mimi-seed init`, then register an app.\n",
|
|
325
|
+
app: (name) => `App: ${name}
|
|
326
|
+
|
|
327
|
+
`,
|
|
328
|
+
appsParseFailed: (raw) => `Failed to parse the app list: ${raw}
|
|
329
|
+
`,
|
|
330
|
+
scoring: "\u{1F4CA} Computing the readiness score...\n",
|
|
331
|
+
scoreFailed: (msg) => `Failed to fetch the score: ${msg}
|
|
332
|
+
`,
|
|
333
|
+
score: (bar) => `
|
|
334
|
+
Score: ${bar}
|
|
335
|
+
|
|
336
|
+
`,
|
|
337
|
+
byModule: "\u2500\u2500 By module \u2500\u2500\n",
|
|
338
|
+
blockers: "\u{1F6AB} Blockers:\n",
|
|
339
|
+
warnings: "\u26A0 Warnings:\n",
|
|
340
|
+
stepIntegration: (url) => `Connections ${url}`,
|
|
341
|
+
stepCopy: (url) => `Copy mimi-seed notes or ${url}`,
|
|
342
|
+
stepScreenshot: (url) => `Screenshots ${url}`,
|
|
343
|
+
stepChecklist: (url) => `Checklist ${url}`,
|
|
344
|
+
nextSteps: "\u2192 Next steps:\n",
|
|
345
|
+
preview: " Preview: mimi-seed deploy --dry-run\n\n",
|
|
346
|
+
ready: "\u2713 Ready to launch!\n",
|
|
347
|
+
notReady: (score) => `Still ${score}/100 \u2014 work through the next steps above.
|
|
348
|
+
`
|
|
349
|
+
}
|
|
350
|
+
);
|
|
270
351
|
function parseArgs(argv) {
|
|
271
352
|
const args = { failOnBlocker: false };
|
|
272
353
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -291,14 +372,13 @@ async function cmdCheck(argv) {
|
|
|
291
372
|
const args = parseArgs(argv);
|
|
292
373
|
const cfg = await getEffectiveConfig();
|
|
293
374
|
if (!cfg) {
|
|
294
|
-
process.stdout.write(kleur2.red(
|
|
375
|
+
process.stdout.write(kleur2.red(M2().noAccount));
|
|
295
376
|
process.exit(1);
|
|
296
377
|
}
|
|
297
|
-
process.stdout.write(kleur2.bold(
|
|
378
|
+
process.stdout.write(kleur2.bold(M2().title));
|
|
298
379
|
const appsResult = await mcpCall(cfg.endpoint, cfg.token, "list_apps", {});
|
|
299
380
|
if (appsResult.isError) {
|
|
300
|
-
process.stdout.write(kleur2.red(
|
|
301
|
-
`));
|
|
381
|
+
process.stdout.write(kleur2.red(M2().appsFailed(appsResult.text)));
|
|
302
382
|
process.exit(1);
|
|
303
383
|
}
|
|
304
384
|
let appId = args.appId;
|
|
@@ -306,36 +386,29 @@ async function cmdCheck(argv) {
|
|
|
306
386
|
try {
|
|
307
387
|
const apps = JSON.parse(appsResult.text);
|
|
308
388
|
if (!Array.isArray(apps) || apps.length === 0) {
|
|
309
|
-
process.stdout.write(kleur2.yellow(
|
|
389
|
+
process.stdout.write(kleur2.yellow(M2().noApps));
|
|
310
390
|
process.exit(0);
|
|
311
391
|
}
|
|
312
392
|
appId = apps[0].id;
|
|
313
|
-
process.stdout.write(kleur2.dim(
|
|
314
|
-
|
|
315
|
-
`));
|
|
393
|
+
process.stdout.write(kleur2.dim(M2().app(apps[0].name ?? appId)));
|
|
316
394
|
} catch {
|
|
317
|
-
process.stdout.write(kleur2.red(
|
|
318
|
-
`));
|
|
395
|
+
process.stdout.write(kleur2.red(M2().appsParseFailed(appsResult.text.slice(0, 80))));
|
|
319
396
|
process.exit(1);
|
|
320
397
|
}
|
|
321
398
|
}
|
|
322
|
-
process.stdout.write(
|
|
399
|
+
process.stdout.write(M2().scoring);
|
|
323
400
|
const readinessResult = await mcpCall(cfg.endpoint, cfg.token, "get_readiness", { app_id: appId });
|
|
324
401
|
if (readinessResult.isError) {
|
|
325
|
-
process.stdout.write(kleur2.red(
|
|
326
|
-
`));
|
|
402
|
+
process.stdout.write(kleur2.red(M2().scoreFailed(readinessResult.text)));
|
|
327
403
|
process.exit(1);
|
|
328
404
|
}
|
|
329
405
|
let hasBlocker = false;
|
|
330
406
|
try {
|
|
331
407
|
const data = JSON.parse(readinessResult.text);
|
|
332
408
|
const score = data.score ?? 0;
|
|
333
|
-
process.stdout.write(
|
|
334
|
-
\uC810\uC218: ${renderScore(score)}
|
|
335
|
-
|
|
336
|
-
`);
|
|
409
|
+
process.stdout.write(M2().score(renderScore(score)));
|
|
337
410
|
if (data.modules) {
|
|
338
|
-
process.stdout.write(kleur2.dim(
|
|
411
|
+
process.stdout.write(kleur2.dim(M2().byModule));
|
|
339
412
|
for (const [key, val] of Object.entries(data.modules)) {
|
|
340
413
|
const label = MODULE_LABELS[key] ?? key;
|
|
341
414
|
const color = val >= 25 ? kleur2.green : val >= 10 ? kleur2.yellow : kleur2.red;
|
|
@@ -346,13 +419,13 @@ async function cmdCheck(argv) {
|
|
|
346
419
|
}
|
|
347
420
|
if (data.blockers?.length) {
|
|
348
421
|
hasBlocker = true;
|
|
349
|
-
process.stdout.write(kleur2.bold(
|
|
422
|
+
process.stdout.write(kleur2.bold(M2().blockers));
|
|
350
423
|
for (const b of data.blockers) process.stdout.write(` ${kleur2.red("\u2022")} ${b}
|
|
351
424
|
`);
|
|
352
425
|
process.stdout.write("\n");
|
|
353
426
|
}
|
|
354
427
|
if (data.warnings?.length) {
|
|
355
|
-
process.stdout.write(kleur2.bold(
|
|
428
|
+
process.stdout.write(kleur2.bold(M2().warnings));
|
|
356
429
|
for (const w of data.warnings) process.stdout.write(` ${kleur2.yellow("\u2022")} ${w}
|
|
357
430
|
`);
|
|
358
431
|
process.stdout.write("\n");
|
|
@@ -360,22 +433,19 @@ async function cmdCheck(argv) {
|
|
|
360
433
|
const base = `${cfg.webBase}/apps/${appId}`;
|
|
361
434
|
const nextSteps = [];
|
|
362
435
|
if (data.modules) {
|
|
363
|
-
if ((data.modules.integration ?? 25) < 25) nextSteps.push(
|
|
364
|
-
if ((data.modules.copy ?? 25) < 25) nextSteps.push(
|
|
365
|
-
if ((data.modules.screenshot ?? 25) < 25) nextSteps.push(
|
|
366
|
-
if ((data.modules.checklist ?? 25) < 25) nextSteps.push(
|
|
436
|
+
if ((data.modules.integration ?? 25) < 25) nextSteps.push(M2().stepIntegration(`${base}/integration`));
|
|
437
|
+
if ((data.modules.copy ?? 25) < 25) nextSteps.push(M2().stepCopy(`${base}/copy`));
|
|
438
|
+
if ((data.modules.screenshot ?? 25) < 25) nextSteps.push(M2().stepScreenshot(`${base}/screenshots`));
|
|
439
|
+
if ((data.modules.checklist ?? 25) < 25) nextSteps.push(M2().stepChecklist(`${base}/launch`));
|
|
367
440
|
}
|
|
368
441
|
if (nextSteps.length) {
|
|
369
|
-
process.stdout.write(kleur2.bold(
|
|
442
|
+
process.stdout.write(kleur2.bold(M2().nextSteps));
|
|
370
443
|
for (const s of nextSteps) process.stdout.write(` ${kleur2.cyan("\u2022")} ${s}
|
|
371
444
|
`);
|
|
372
|
-
process.stdout.write(kleur2.dim(
|
|
373
|
-
|
|
374
|
-
`));
|
|
445
|
+
process.stdout.write(kleur2.dim(M2().preview));
|
|
375
446
|
}
|
|
376
447
|
if (!hasBlocker) {
|
|
377
|
-
process.stdout.write(score >= 80 ? kleur2.green(
|
|
378
|
-
`));
|
|
448
|
+
process.stdout.write(score >= 80 ? kleur2.green(M2().ready) : kleur2.yellow(M2().notReady(score)));
|
|
379
449
|
}
|
|
380
450
|
} catch {
|
|
381
451
|
for (const line of readinessResult.text.split("\n")) process.stdout.write(" " + line + "\n");
|
|
@@ -387,6 +457,122 @@ async function cmdCheck(argv) {
|
|
|
387
457
|
import { createInterface } from "readline/promises";
|
|
388
458
|
import Anthropic from "@anthropic-ai/sdk";
|
|
389
459
|
import kleur3 from "kleur";
|
|
460
|
+
var M3 = catalog(
|
|
461
|
+
{
|
|
462
|
+
// Claude 프롬프트
|
|
463
|
+
localeHint: (l) => `"${l}": "\uD574\uB2F9 \uC5B8\uC5B4\uB85C \uBC88\uC5ED\uB41C \uAC04\uACB0\uD55C \uBC84\uC804"`,
|
|
464
|
+
system: "\uC571 \uC2A4\uD1A0\uC5B4 \uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC804\uBB38 \uCE74\uD53C\uB77C\uC774\uD130\uC785\uB2C8\uB2E4. \uCEE4\uBC0B \uB0B4\uC5ED\uC744 \uC0AC\uC6A9\uC790 \uCE5C\uD654\uC801\uC778 \uC5B8\uC5B4\uB85C \uBCC0\uD658\uD569\uB2C8\uB2E4. \uD56D\uC0C1 \uC720\uD6A8\uD55C JSON\uC73C\uB85C\uB9CC \uC751\uB2F5\uD558\uC138\uC694.",
|
|
465
|
+
userPrompt: (commitsText, localeList) => `\uB2E4\uC74C \uCEE4\uBC0B \uB0B4\uC5ED\uC73C\uB85C \uB9B4\uB9AC\uC988 \uB178\uD2B8\uB97C 3\uAC00\uC9C0 \uD1A4\uC73C\uB85C \uC791\uC131\uD558\uC138\uC694:
|
|
466
|
+
|
|
467
|
+
${commitsText}
|
|
468
|
+
|
|
469
|
+
JSON:
|
|
470
|
+
{
|
|
471
|
+
"concise": "\uAC04\uACB0\uD55C \uBC84\uC804 (3\uC904 \uC774\uB0B4, \uBD88\uB9BF)",
|
|
472
|
+
"detailed": "\uC0C1\uC138 \uBC84\uC804 (5\uAC1C \uC774\uB0B4, \uBD88\uB9BF)",
|
|
473
|
+
"marketing": "\uB9C8\uCF00\uD305 \uBC84\uC804 (\uC5F4\uC815\uC801 \uD1A4)",
|
|
474
|
+
"localized": {
|
|
475
|
+
${localeList}
|
|
476
|
+
}
|
|
477
|
+
}`,
|
|
478
|
+
parseFailed: "AI \uC751\uB2F5 \uD30C\uC2F1 \uC2E4\uD328",
|
|
479
|
+
// 템플릿 폴백
|
|
480
|
+
marketingTemplate: (items) => `\uC0C8\uB85C\uC6B4 \uC5C5\uB370\uC774\uD2B8\uAC00 \uC900\uBE44\uB410\uC2B5\uB2C8\uB2E4!
|
|
481
|
+
|
|
482
|
+
${items}
|
|
483
|
+
|
|
484
|
+
\uC9C0\uAE08 \uBC14\uB85C \uC5C5\uB370\uC774\uD2B8\uD558\uC138\uC694.`,
|
|
485
|
+
// cmdNotes
|
|
486
|
+
title: "mimi-seed notes \u2014 \uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC0DD\uC131\n\n",
|
|
487
|
+
notGitRepo: "Git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2D9\uB2C8\uB2E4.\n",
|
|
488
|
+
range: (from, to) => `\uBC94\uC704: ${from} \u2192 ${to}
|
|
489
|
+
`,
|
|
490
|
+
recentCommits: (limit) => `\uCD5C\uADFC ${limit}\uAC1C \uCEE4\uBC0B
|
|
491
|
+
`,
|
|
492
|
+
noCommits: "\uCEE4\uBC0B\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.\n",
|
|
493
|
+
analyzing: (n) => `\uCEE4\uBC0B ${n}\uAC1C \uBD84\uC11D \uC911...
|
|
494
|
+
|
|
495
|
+
`,
|
|
496
|
+
generating: "\u{1F916} Claude AI\uB85C \uC0DD\uC131 \uC911...\n",
|
|
497
|
+
aiFailed: (msg) => `AI \uC0DD\uC131 \uC2E4\uD328, \uD15C\uD50C\uB9BF \uC0AC\uC6A9: ${msg}
|
|
498
|
+
`,
|
|
499
|
+
noApiKey: "ANTHROPIC_API_KEY \uC5C6\uC74C \u2014 \uC790\uB3D9 \uD3EC\uB9F7\uD305 \uC0AC\uC6A9\n",
|
|
500
|
+
noApiKeyHint: "AI \uC0DD\uC131 \uD65C\uC131\uD654: export ANTHROPIC_API_KEY=sk-ant-...\n\n",
|
|
501
|
+
hdrConcise: "\u2500\u2500\u2500 \uAC04\uACB0\uD55C \uBC84\uC804 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
|
|
502
|
+
hdrDetailed: "\u2500\u2500\u2500 \uC0C1\uC138 \uBC84\uC804 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
|
|
503
|
+
hdrMarketing: "\u2500\u2500\u2500 \uB9C8\uCF00\uD305 \uBC84\uC804 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
|
|
504
|
+
hdrLocalized: "\u2500\u2500\u2500 \uB2E4\uAD6D\uC5B4 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
|
|
505
|
+
needAccount: "Mimi Seed \uACC4\uC815 \uC5F0\uACB0 \uD544\uC694. `mimi-seed init` \uC2E4\uD589.\n",
|
|
506
|
+
choosePrompt: "\uC801\uC6A9\uD560 \uBC84\uC804 [1=\uAC04\uACB0/2=\uC0C1\uC138/3=\uB9C8\uCF00\uD305/Enter=\uAC74\uB108\uB700]: ",
|
|
507
|
+
skipped: "\uAC74\uB108\uB700.\n",
|
|
508
|
+
listAppsFailed: (msg) => `\uC571 \uBAA9\uB85D \uC870\uD68C \uC2E4\uD328: ${msg}
|
|
509
|
+
`,
|
|
510
|
+
noApps: "\uB4F1\uB85D\uB41C \uC571\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\n",
|
|
511
|
+
toneToAllLocales: "\uC120\uD0DD\uD55C \uD1A4\uC744 \uBAA8\uB4E0 \uB85C\uCF00\uC77C\uC5D0 \uC801\uC6A9\uD569\uB2C8\uB2E4 (\uC790\uB3D9 \uBC88\uC5ED \uBBF8\uC801\uC6A9).\n",
|
|
512
|
+
applying: "Play Store\uC5D0 \uC801\uC6A9 \uC911...\n",
|
|
513
|
+
applyFailed: (locale, msg) => `${locale} \uC801\uC6A9 \uC2E4\uD328: ${msg}
|
|
514
|
+
`,
|
|
515
|
+
applied: (locale) => `\u2713 ${locale} \uC801\uC6A9\uB428
|
|
516
|
+
`
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
// Claude prompt
|
|
520
|
+
localeHint: (l) => `"${l}": "the concise version, translated into that language"`,
|
|
521
|
+
system: "You are an expert app store release-notes copywriter. You turn commit history into user-friendly language. Always respond with valid JSON only.",
|
|
522
|
+
userPrompt: (commitsText, localeList) => `Write release notes in 3 tones from the following commit history:
|
|
523
|
+
|
|
524
|
+
${commitsText}
|
|
525
|
+
|
|
526
|
+
JSON:
|
|
527
|
+
{
|
|
528
|
+
"concise": "concise version (3 bullets max)",
|
|
529
|
+
"detailed": "detailed version (5 bullets max)",
|
|
530
|
+
"marketing": "marketing version (enthusiastic tone)",
|
|
531
|
+
"localized": {
|
|
532
|
+
${localeList}
|
|
533
|
+
}
|
|
534
|
+
}`,
|
|
535
|
+
parseFailed: "Failed to parse the AI response",
|
|
536
|
+
// Template fallback
|
|
537
|
+
marketingTemplate: (items) => `A new update is here!
|
|
538
|
+
|
|
539
|
+
${items}
|
|
540
|
+
|
|
541
|
+
Update now.`,
|
|
542
|
+
// cmdNotes
|
|
543
|
+
title: "mimi-seed notes \u2014 generate release notes\n\n",
|
|
544
|
+
notGitRepo: "Not a git repository.\n",
|
|
545
|
+
range: (from, to) => `Range: ${from} \u2192 ${to}
|
|
546
|
+
`,
|
|
547
|
+
recentCommits: (limit) => `Last ${limit} commit(s)
|
|
548
|
+
`,
|
|
549
|
+
noCommits: "No commits found.\n",
|
|
550
|
+
analyzing: (n) => `Analyzing ${n} commit(s)...
|
|
551
|
+
|
|
552
|
+
`,
|
|
553
|
+
generating: "\u{1F916} Generating with Claude AI...\n",
|
|
554
|
+
aiFailed: (msg) => `AI generation failed, falling back to the template: ${msg}
|
|
555
|
+
`,
|
|
556
|
+
noApiKey: "No ANTHROPIC_API_KEY \u2014 using automatic formatting\n",
|
|
557
|
+
noApiKeyHint: "Enable AI generation: export ANTHROPIC_API_KEY=sk-ant-...\n\n",
|
|
558
|
+
hdrConcise: "\u2500\u2500\u2500 Concise \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
|
|
559
|
+
hdrDetailed: "\u2500\u2500\u2500 Detailed \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
|
|
560
|
+
hdrMarketing: "\u2500\u2500\u2500 Marketing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
|
|
561
|
+
hdrLocalized: "\u2500\u2500\u2500 Localized \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
|
|
562
|
+
needAccount: "A Mimi Seed account is required. Run `mimi-seed init`.\n",
|
|
563
|
+
choosePrompt: "Which version? [1=concise/2=detailed/3=marketing/Enter=skip]: ",
|
|
564
|
+
skipped: "Skipped.\n",
|
|
565
|
+
listAppsFailed: (msg) => `Failed to list apps: ${msg}
|
|
566
|
+
`,
|
|
567
|
+
noApps: "No apps registered.\n",
|
|
568
|
+
toneToAllLocales: "Applying the selected tone to every locale (no automatic translation).\n",
|
|
569
|
+
applying: "Applying to Play Store...\n",
|
|
570
|
+
applyFailed: (locale, msg) => `${locale} failed to apply: ${msg}
|
|
571
|
+
`,
|
|
572
|
+
applied: (locale) => `\u2713 ${locale} applied
|
|
573
|
+
`
|
|
574
|
+
}
|
|
575
|
+
);
|
|
390
576
|
function parseArgs2(argv) {
|
|
391
577
|
const args = { to: "HEAD", locales: ["ko", "en-US"], apply: false, noInteractive: false, limit: 30 };
|
|
392
578
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -407,31 +593,19 @@ async function promptUser(question) {
|
|
|
407
593
|
}
|
|
408
594
|
async function generateWithClaude(commitsText, locales) {
|
|
409
595
|
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
|
|
410
|
-
const localeList = locales.map((l) =>
|
|
596
|
+
const localeList = locales.map((l) => M3().localeHint(l)).join(",\n ");
|
|
411
597
|
const response = await client.messages.create({
|
|
412
598
|
model: "claude-haiku-4-5-20251001",
|
|
413
599
|
max_tokens: 1500,
|
|
414
|
-
system:
|
|
600
|
+
system: M3().system,
|
|
415
601
|
messages: [{
|
|
416
602
|
role: "user",
|
|
417
|
-
content:
|
|
418
|
-
|
|
419
|
-
${commitsText}
|
|
420
|
-
|
|
421
|
-
JSON:
|
|
422
|
-
{
|
|
423
|
-
"concise": "\uAC04\uACB0\uD55C \uBC84\uC804 (3\uC904 \uC774\uB0B4, \uBD88\uB9BF)",
|
|
424
|
-
"detailed": "\uC0C1\uC138 \uBC84\uC804 (5\uAC1C \uC774\uB0B4, \uBD88\uB9BF)",
|
|
425
|
-
"marketing": "\uB9C8\uCF00\uD305 \uBC84\uC804 (\uC5F4\uC815\uC801 \uD1A4)",
|
|
426
|
-
"localized": {
|
|
427
|
-
${localeList}
|
|
428
|
-
}
|
|
429
|
-
}`
|
|
603
|
+
content: M3().userPrompt(commitsText, localeList)
|
|
430
604
|
}]
|
|
431
605
|
});
|
|
432
606
|
const text = response.content[0].type === "text" ? response.content[0].text : "";
|
|
433
607
|
const match = text.match(/\{[\s\S]*\}/);
|
|
434
|
-
if (!match) throw new Error(
|
|
608
|
+
if (!match) throw new Error(M3().parseFailed);
|
|
435
609
|
return JSON.parse(match[0]);
|
|
436
610
|
}
|
|
437
611
|
function generateTemplate(commits, locales) {
|
|
@@ -441,11 +615,7 @@ function generateTemplate(commits, locales) {
|
|
|
441
615
|
});
|
|
442
616
|
const concise = items.slice(0, 3).join("\n");
|
|
443
617
|
const detailed = items.join("\n");
|
|
444
|
-
const marketing =
|
|
445
|
-
|
|
446
|
-
${items.slice(0, 5).join("\n")}
|
|
447
|
-
|
|
448
|
-
\uC9C0\uAE08 \uBC14\uB85C \uC5C5\uB370\uC774\uD2B8\uD558\uC138\uC694.`;
|
|
618
|
+
const marketing = M3().marketingTemplate(items.slice(0, 5).join("\n"));
|
|
449
619
|
const localized = Object.fromEntries(locales.map((l) => [l, concise]));
|
|
450
620
|
return { concise, detailed, marketing, localized };
|
|
451
621
|
}
|
|
@@ -460,46 +630,43 @@ function parseFirstApp(text) {
|
|
|
460
630
|
async function cmdNotes(argv) {
|
|
461
631
|
const args = parseArgs2(argv);
|
|
462
632
|
const cwd = process.cwd();
|
|
463
|
-
process.stdout.write(kleur3.bold(
|
|
633
|
+
process.stdout.write(kleur3.bold(M3().title));
|
|
464
634
|
if (!isGitRepo(cwd)) {
|
|
465
|
-
process.stdout.write(kleur3.red(
|
|
635
|
+
process.stdout.write(kleur3.red(M3().notGitRepo));
|
|
466
636
|
process.exit(1);
|
|
467
637
|
}
|
|
468
638
|
const latestTag = getLatestTag(cwd);
|
|
469
639
|
const fromRef = args.from ?? latestTag ?? void 0;
|
|
470
|
-
process.stdout.write(
|
|
471
|
-
|
|
472
|
-
|
|
640
|
+
process.stdout.write(
|
|
641
|
+
kleur3.dim(fromRef ? M3().range(fromRef, args.to) : M3().recentCommits(args.limit))
|
|
642
|
+
);
|
|
473
643
|
const commits = getGitLog(cwd, { from: fromRef, to: args.to, limit: args.limit });
|
|
474
644
|
if (commits.length === 0) {
|
|
475
|
-
process.stdout.write(kleur3.yellow(
|
|
645
|
+
process.stdout.write(kleur3.yellow(M3().noCommits));
|
|
476
646
|
process.exit(0);
|
|
477
647
|
}
|
|
478
|
-
process.stdout.write(kleur3.dim(
|
|
479
|
-
|
|
480
|
-
`));
|
|
648
|
+
process.stdout.write(kleur3.dim(M3().analyzing(commits.length)));
|
|
481
649
|
let result;
|
|
482
650
|
if (process.env.ANTHROPIC_API_KEY) {
|
|
483
|
-
process.stdout.write(
|
|
651
|
+
process.stdout.write(M3().generating);
|
|
484
652
|
try {
|
|
485
653
|
result = await generateWithClaude(formatCommitsForPrompt(commits), args.locales);
|
|
486
654
|
} catch (e) {
|
|
487
|
-
process.stdout.write(kleur3.yellow(
|
|
488
|
-
`));
|
|
655
|
+
process.stdout.write(kleur3.yellow(M3().aiFailed(e.message)));
|
|
489
656
|
result = generateTemplate(commits, args.locales);
|
|
490
657
|
}
|
|
491
658
|
} else {
|
|
492
|
-
process.stdout.write(kleur3.dim(
|
|
659
|
+
process.stdout.write(kleur3.dim(M3().noApiKey) + kleur3.dim(M3().noApiKeyHint));
|
|
493
660
|
result = generateTemplate(commits, args.locales);
|
|
494
661
|
}
|
|
495
|
-
process.stdout.write(kleur3.bold(
|
|
662
|
+
process.stdout.write(kleur3.bold(M3().hdrConcise));
|
|
496
663
|
process.stdout.write(result.concise + "\n\n");
|
|
497
|
-
process.stdout.write(kleur3.bold(
|
|
664
|
+
process.stdout.write(kleur3.bold(M3().hdrDetailed));
|
|
498
665
|
process.stdout.write(result.detailed + "\n\n");
|
|
499
|
-
process.stdout.write(kleur3.bold(
|
|
666
|
+
process.stdout.write(kleur3.bold(M3().hdrMarketing));
|
|
500
667
|
process.stdout.write(result.marketing + "\n\n");
|
|
501
668
|
if (Object.keys(result.localized).length > 0) {
|
|
502
|
-
process.stdout.write(kleur3.bold(
|
|
669
|
+
process.stdout.write(kleur3.bold(M3().hdrLocalized));
|
|
503
670
|
for (const [locale, text] of Object.entries(result.localized)) {
|
|
504
671
|
process.stdout.write(kleur3.dim(`[${locale}]
|
|
505
672
|
`) + text + "\n\n");
|
|
@@ -509,15 +676,15 @@ async function cmdNotes(argv) {
|
|
|
509
676
|
if (!args.apply && !shouldPrompt) return;
|
|
510
677
|
const cfg = await getEffectiveConfig();
|
|
511
678
|
if (!cfg) {
|
|
512
|
-
process.stdout.write(kleur3.yellow(
|
|
679
|
+
process.stdout.write(kleur3.yellow(M3().needAccount));
|
|
513
680
|
return;
|
|
514
681
|
}
|
|
515
682
|
let selectedText = result.concise;
|
|
516
683
|
let userSelectedTone = false;
|
|
517
684
|
if (shouldPrompt) {
|
|
518
|
-
const choice = await promptUser(
|
|
685
|
+
const choice = await promptUser(M3().choosePrompt);
|
|
519
686
|
if (!choice) {
|
|
520
|
-
process.stdout.write(kleur3.dim(
|
|
687
|
+
process.stdout.write(kleur3.dim(M3().skipped));
|
|
521
688
|
return;
|
|
522
689
|
}
|
|
523
690
|
if (choice === "2") selectedText = result.detailed;
|
|
@@ -526,19 +693,18 @@ async function cmdNotes(argv) {
|
|
|
526
693
|
}
|
|
527
694
|
const appsResult = await mcpCall(cfg.endpoint, cfg.token, "list_apps", {});
|
|
528
695
|
if (appsResult.isError) {
|
|
529
|
-
process.stdout.write(kleur3.red(
|
|
530
|
-
`));
|
|
696
|
+
process.stdout.write(kleur3.red(M3().listAppsFailed(appsResult.text)));
|
|
531
697
|
return;
|
|
532
698
|
}
|
|
533
699
|
const app = parseFirstApp(appsResult.text);
|
|
534
700
|
if (!app) {
|
|
535
|
-
process.stdout.write(kleur3.yellow(
|
|
701
|
+
process.stdout.write(kleur3.yellow(M3().noApps));
|
|
536
702
|
return;
|
|
537
703
|
}
|
|
538
704
|
if (userSelectedTone && args.locales.length > 1) {
|
|
539
|
-
process.stdout.write(kleur3.dim(
|
|
705
|
+
process.stdout.write(kleur3.dim(M3().toneToAllLocales));
|
|
540
706
|
}
|
|
541
|
-
process.stdout.write(
|
|
707
|
+
process.stdout.write(M3().applying);
|
|
542
708
|
for (const locale of args.locales) {
|
|
543
709
|
const text = userSelectedTone ? selectedText : result.localized[locale] ?? selectedText;
|
|
544
710
|
const r = await mcpCall(cfg.endpoint, cfg.token, "apply_release_notes", {
|
|
@@ -547,9 +713,9 @@ async function cmdNotes(argv) {
|
|
|
547
713
|
locale,
|
|
548
714
|
text
|
|
549
715
|
});
|
|
550
|
-
process.stdout.write(
|
|
551
|
-
|
|
552
|
-
|
|
716
|
+
process.stdout.write(
|
|
717
|
+
r.isError ? kleur3.red(M3().applyFailed(locale, r.text)) : kleur3.green(M3().applied(locale))
|
|
718
|
+
);
|
|
553
719
|
}
|
|
554
720
|
}
|
|
555
721
|
|
|
@@ -557,6 +723,120 @@ async function cmdNotes(argv) {
|
|
|
557
723
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
558
724
|
import Anthropic2 from "@anthropic-ai/sdk";
|
|
559
725
|
import kleur4 from "kleur";
|
|
726
|
+
var M4 = catalog(
|
|
727
|
+
{
|
|
728
|
+
toneGuides: {
|
|
729
|
+
friendly: "\uCE5C\uADFC\uD558\uACE0 \uB530\uB73B\uD558\uAC8C. \uC774\uBAA8\uC9C0 1~2\uAC1C \uC0AC\uC6A9. \uAC10\uC0AC \uC778\uC0AC\uB85C \uC2DC\uC791.",
|
|
730
|
+
professional: "\uC815\uC911\uD558\uACE0 \uACF5\uC2DD\uC801\uC73C\uB85C. \uBB38\uC81C\uB97C \uC778\uC815\uD558\uACE0 \uD574\uACB0\uCC45\uC744 \uC81C\uC2DC.",
|
|
731
|
+
empathetic: "\uACF5\uAC10\uC744 \uBA3C\uC800 \uD45C\uD604. \uBD88\uD3B8\uC744 \uCDA9\uBD84\uD788 \uC778\uC815\uD55C \uD6C4 \uD574\uACB0 \uC758\uC9C0\uB97C \uBCF4\uC5EC\uC90C.",
|
|
732
|
+
brief: "2~3\uBB38\uC7A5\uC73C\uB85C \uAC04\uACB0\uD558\uAC8C. \uD575\uC2EC \uC751\uB2F5\uB9CC."
|
|
733
|
+
},
|
|
734
|
+
sentimentPrompts: {
|
|
735
|
+
positive: "\uAE0D\uC815\uC801\uC778 \uB9AC\uBDF0. \uAC10\uC0AC \uC778\uC0AC\uC640 \uD568\uAED8 \uC55E\uC73C\uB85C\uB3C4 \uC88B\uC740 \uACBD\uD5D8\uC744 \uC81C\uACF5\uD558\uACA0\uB2E4\uB294 \uC758\uC9C0\uB97C \uD45C\uD604.",
|
|
736
|
+
negative: "\uBD80\uC815\uC801\uC778 \uB9AC\uBDF0. \uBA3C\uC800 \uBD88\uD3B8\uC744 \uC0AC\uACFC\uD558\uACE0, \uBB38\uC81C \uD574\uACB0 \uC758\uC9C0\uB97C \uBCF4\uC5EC\uC918. \uAC00\uB2A5\uD558\uBA74 \uC9C0\uC6D0 \uCC44\uB110\uB85C \uC720\uB3C4.",
|
|
737
|
+
neutral: "\uC911\uB9BD\uC801\uC778 \uB9AC\uBDF0. \uD53C\uB4DC\uBC31\uC5D0 \uAC10\uC0AC\uD558\uACE0 \uAC1C\uC120 \uB178\uB825\uC744 \uC57D\uC18D.",
|
|
738
|
+
bug_report: "\uBC84\uADF8 \uB9AC\uD3EC\uD2B8. \uBB38\uC81C\uB97C \uD655\uC778\uD588\uC74C\uC744 \uC54C\uB9AC\uACE0, \uC218\uC815 \uC608\uC815\uC784\uC744 \uC804\uB2EC.",
|
|
739
|
+
feature_request: "\uAE30\uB2A5 \uC694\uCCAD. \uD53C\uB4DC\uBC31\uC5D0 \uAC10\uC0AC\uD558\uACE0, \uAC80\uD1A0\uD558\uACA0\uB2E4\uACE0 \uC57D\uC18D."
|
|
740
|
+
},
|
|
741
|
+
localeNames: { ko: "\uD55C\uAD6D\uC5B4", en: "\uC601\uC5B4", ja: "\uC77C\uBCF8\uC5B4", "en-US": "\uC601\uC5B4", "zh-TW": "\uBC88\uCCB4\uC911\uAD6D\uC5B4" },
|
|
742
|
+
// Claude 프롬프트
|
|
743
|
+
starsLabel: (stars, rating) => `\uBCC4\uC810: ${stars} (${rating}/5)
|
|
744
|
+
`,
|
|
745
|
+
defaultDeveloper: "\uAC1C\uBC1C\uD300",
|
|
746
|
+
defaultApp: "\uC571",
|
|
747
|
+
system: (langName, toneGuide, developer) => `\uC571 \uAC1C\uBC1C\uC790\uB97C \uB300\uC2E0\uD574 \uC2A4\uD1A0\uC5B4 \uB9AC\uBDF0\uC5D0 \uB2F5\uBCC0\uD558\uB294 \uC804\uBB38\uAC00. ${langName}\uB85C 150\uC790 \uC774\uB0B4\uB85C \uB2F5\uBCC0. ${toneGuide} \uAC1C\uBC1C\uC790 \uC774\uB984: ${developer}`,
|
|
748
|
+
userPrompt: (app, stars, text, sentimentPrompt) => `\uC571: ${app}
|
|
749
|
+
${stars}\uB9AC\uBDF0: "${text}"
|
|
750
|
+
|
|
751
|
+
\uC9C0\uCE68: ${sentimentPrompt}
|
|
752
|
+
|
|
753
|
+
JSON\uC73C\uB85C\uB9CC \uC751\uB2F5: { "reply": "\uB2F5\uBCC0 \uD14D\uC2A4\uD2B8" }`,
|
|
754
|
+
parseFailed: "AI \uC751\uB2F5 \uD30C\uC2F1 \uC2E4\uD328",
|
|
755
|
+
// cmdReview
|
|
756
|
+
title: "mimi-seed review \u2014 \uB9AC\uBDF0 \uB2F5\uBCC0 \uC0DD\uC131\n\n",
|
|
757
|
+
noApiKey: "ANTHROPIC_API_KEY\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.\n",
|
|
758
|
+
noApiKeyHint: "\uD65C\uC131\uD654: export ANTHROPIC_API_KEY=sk-ant-...\n",
|
|
759
|
+
textRequired: "--text <\uB9AC\uBDF0 \uB0B4\uC6A9> \uC774 \uD544\uC694\uD569\uB2C8\uB2E4.\n",
|
|
760
|
+
enterReview: "\uB9AC\uBDF0 \uB0B4\uC6A9\uC744 \uC785\uB825\uD558\uC138\uC694 (\uC5EC\uB7EC \uC904: Ctrl+D\uB85C \uC644\uB8CC):\n",
|
|
761
|
+
noInput: "\uC785\uB825 \uC5C6\uC74C. \uC885\uB8CC.\n",
|
|
762
|
+
meta: (stars, tone, language) => `\uBCC4\uC810: ${stars} tone: ${tone} \uC5B8\uC5B4: ${language}
|
|
763
|
+
|
|
764
|
+
`,
|
|
765
|
+
generating: "\u{1F916} Claude AI\uB85C \uB2F5\uBCC0 \uC0DD\uC131 \uC911...\n",
|
|
766
|
+
hdrReply: "\u2500\u2500\u2500 \uC81C\uC548 \uB2F5\uBCC0 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
|
|
767
|
+
draftWarning: "\n\u26A0 \uC774 \uB2F5\uBCC0\uC740 AI\uAC00 \uC0DD\uC131\uD55C \uCD08\uC548\uC785\uB2C8\uB2E4. \uAC8C\uC2DC \uC804 \uBC18\uB4DC\uC2DC \uAC80\uD1A0\uD558\uC138\uC694.\n\n",
|
|
768
|
+
postPrompt: "\uC774 \uB2F5\uBCC0\uC744 Play Store\uC5D0 \uAC8C\uC2DC\uD560\uAE4C\uC694? [y/N]: ",
|
|
769
|
+
skipped: "\uAC74\uB108\uB700.\n",
|
|
770
|
+
needAccount: "Mimi Seed \uACC4\uC815 \uC5F0\uACB0 \uD544\uC694. `mimi-seed init` \uC2E4\uD589.\n",
|
|
771
|
+
idsRequired: "--review-id \uC640 --package-name \uC774 \uD544\uC694\uD569\uB2C8\uB2E4.\n",
|
|
772
|
+
packagePrompt: "\uD328\uD0A4\uC9C0\uBA85 (\uC608: com.example.app): ",
|
|
773
|
+
reviewIdPrompt: "\uB9AC\uBDF0 ID: ",
|
|
774
|
+
notEnoughInfo: "\uC815\uBCF4 \uBD80\uC871. \uCDE8\uC18C.\n",
|
|
775
|
+
posting: "Play Store\uC5D0 \uAC8C\uC2DC \uC911...\n",
|
|
776
|
+
postFailed: (msg) => `\uAC8C\uC2DC \uC2E4\uD328: ${msg}
|
|
777
|
+
`,
|
|
778
|
+
posted: "\u2713 \uB2F5\uBCC0 \uAC8C\uC2DC \uC644\uB8CC\n"
|
|
779
|
+
},
|
|
780
|
+
{
|
|
781
|
+
toneGuides: {
|
|
782
|
+
friendly: "Warm and friendly. Use 1-2 emoji. Open with a thank-you.",
|
|
783
|
+
professional: "Polite and formal. Acknowledge the issue and offer a solution.",
|
|
784
|
+
empathetic: "Lead with empathy. Fully acknowledge the frustration, then show a commitment to fix it.",
|
|
785
|
+
brief: "Keep it to 2-3 sentences. Only the essential response."
|
|
786
|
+
},
|
|
787
|
+
sentimentPrompts: {
|
|
788
|
+
positive: "A positive review. Say thank you and commit to keeping the experience great.",
|
|
789
|
+
negative: "A negative review. Apologize for the trouble first, then show a commitment to fixing it. Point to a support channel if you can.",
|
|
790
|
+
neutral: "A neutral review. Thank them for the feedback and promise to keep improving.",
|
|
791
|
+
bug_report: "A bug report. Confirm the issue is known and say a fix is coming.",
|
|
792
|
+
feature_request: "A feature request. Thank them for the feedback and promise to consider it."
|
|
793
|
+
},
|
|
794
|
+
localeNames: {
|
|
795
|
+
ko: "Korean",
|
|
796
|
+
en: "English",
|
|
797
|
+
ja: "Japanese",
|
|
798
|
+
"en-US": "English",
|
|
799
|
+
"zh-TW": "Traditional Chinese"
|
|
800
|
+
},
|
|
801
|
+
// Claude prompt
|
|
802
|
+
starsLabel: (stars, rating) => `Rating: ${stars} (${rating}/5)
|
|
803
|
+
`,
|
|
804
|
+
defaultDeveloper: "the dev team",
|
|
805
|
+
defaultApp: "the app",
|
|
806
|
+
system: (langName, toneGuide, developer) => `You reply to app store reviews on behalf of the app's developer. Reply in ${langName}, in 150 characters or fewer. ${toneGuide} Developer name: ${developer}`,
|
|
807
|
+
userPrompt: (app, stars, text, sentimentPrompt) => `App: ${app}
|
|
808
|
+
${stars}Review: "${text}"
|
|
809
|
+
|
|
810
|
+
Guidance: ${sentimentPrompt}
|
|
811
|
+
|
|
812
|
+
Respond with JSON only: { "reply": "the reply text" }`,
|
|
813
|
+
parseFailed: "Failed to parse the AI response",
|
|
814
|
+
// cmdReview
|
|
815
|
+
title: "mimi-seed review \u2014 generate a review reply\n\n",
|
|
816
|
+
noApiKey: "ANTHROPIC_API_KEY is not set.\n",
|
|
817
|
+
noApiKeyHint: "Enable it: export ANTHROPIC_API_KEY=sk-ant-...\n",
|
|
818
|
+
textRequired: "--text <review body> is required.\n",
|
|
819
|
+
enterReview: "Paste the review (multi-line: finish with Ctrl+D):\n",
|
|
820
|
+
noInput: "Nothing entered. Exiting.\n",
|
|
821
|
+
meta: (stars, tone, language) => `Rating: ${stars} tone: ${tone} language: ${language}
|
|
822
|
+
|
|
823
|
+
`,
|
|
824
|
+
generating: "\u{1F916} Generating a reply with Claude AI...\n",
|
|
825
|
+
hdrReply: "\u2500\u2500\u2500 Suggested reply \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
|
|
826
|
+
draftWarning: "\n\u26A0 This reply is an AI-generated draft. Always review it before posting.\n\n",
|
|
827
|
+
postPrompt: "Post this reply to Play Store? [y/N]: ",
|
|
828
|
+
skipped: "Skipped.\n",
|
|
829
|
+
needAccount: "A Mimi Seed account is required. Run `mimi-seed init`.\n",
|
|
830
|
+
idsRequired: "--review-id and --package-name are required.\n",
|
|
831
|
+
packagePrompt: "Package name (e.g. com.example.app): ",
|
|
832
|
+
reviewIdPrompt: "Review ID: ",
|
|
833
|
+
notEnoughInfo: "Not enough information. Cancelled.\n",
|
|
834
|
+
posting: "Posting to Play Store...\n",
|
|
835
|
+
postFailed: (msg) => `Failed to post: ${msg}
|
|
836
|
+
`,
|
|
837
|
+
posted: "\u2713 Reply posted\n"
|
|
838
|
+
}
|
|
839
|
+
);
|
|
560
840
|
function parseArgs3(argv) {
|
|
561
841
|
const args = { tone: "friendly", language: "ko", apply: false, noInteractive: false };
|
|
562
842
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -579,19 +859,6 @@ async function promptUser2(question) {
|
|
|
579
859
|
rl.close();
|
|
580
860
|
return answer.trim();
|
|
581
861
|
}
|
|
582
|
-
var TONE_GUIDES = {
|
|
583
|
-
friendly: "\uCE5C\uADFC\uD558\uACE0 \uB530\uB73B\uD558\uAC8C. \uC774\uBAA8\uC9C0 1~2\uAC1C \uC0AC\uC6A9. \uAC10\uC0AC \uC778\uC0AC\uB85C \uC2DC\uC791.",
|
|
584
|
-
professional: "\uC815\uC911\uD558\uACE0 \uACF5\uC2DD\uC801\uC73C\uB85C. \uBB38\uC81C\uB97C \uC778\uC815\uD558\uACE0 \uD574\uACB0\uCC45\uC744 \uC81C\uC2DC.",
|
|
585
|
-
empathetic: "\uACF5\uAC10\uC744 \uBA3C\uC800 \uD45C\uD604. \uBD88\uD3B8\uC744 \uCDA9\uBD84\uD788 \uC778\uC815\uD55C \uD6C4 \uD574\uACB0 \uC758\uC9C0\uB97C \uBCF4\uC5EC\uC90C.",
|
|
586
|
-
brief: "2~3\uBB38\uC7A5\uC73C\uB85C \uAC04\uACB0\uD558\uAC8C. \uD575\uC2EC \uC751\uB2F5\uB9CC."
|
|
587
|
-
};
|
|
588
|
-
var SENTIMENT_PROMPTS = {
|
|
589
|
-
positive: "\uAE0D\uC815\uC801\uC778 \uB9AC\uBDF0. \uAC10\uC0AC \uC778\uC0AC\uC640 \uD568\uAED8 \uC55E\uC73C\uB85C\uB3C4 \uC88B\uC740 \uACBD\uD5D8\uC744 \uC81C\uACF5\uD558\uACA0\uB2E4\uB294 \uC758\uC9C0\uB97C \uD45C\uD604.",
|
|
590
|
-
negative: "\uBD80\uC815\uC801\uC778 \uB9AC\uBDF0. \uBA3C\uC800 \uBD88\uD3B8\uC744 \uC0AC\uACFC\uD558\uACE0, \uBB38\uC81C \uD574\uACB0 \uC758\uC9C0\uB97C \uBCF4\uC5EC\uC918. \uAC00\uB2A5\uD558\uBA74 \uC9C0\uC6D0 \uCC44\uB110\uB85C \uC720\uB3C4.",
|
|
591
|
-
neutral: "\uC911\uB9BD\uC801\uC778 \uB9AC\uBDF0. \uD53C\uB4DC\uBC31\uC5D0 \uAC10\uC0AC\uD558\uACE0 \uAC1C\uC120 \uB178\uB825\uC744 \uC57D\uC18D.",
|
|
592
|
-
bug_report: "\uBC84\uADF8 \uB9AC\uD3EC\uD2B8. \uBB38\uC81C\uB97C \uD655\uC778\uD588\uC74C\uC744 \uC54C\uB9AC\uACE0, \uC218\uC815 \uC608\uC815\uC784\uC744 \uC804\uB2EC.",
|
|
593
|
-
feature_request: "\uAE30\uB2A5 \uC694\uCCAD. \uD53C\uB4DC\uBC31\uC5D0 \uAC10\uC0AC\uD558\uACE0, \uAC80\uD1A0\uD558\uACA0\uB2E4\uACE0 \uC57D\uC18D."
|
|
594
|
-
};
|
|
595
862
|
function detectSentiment(text) {
|
|
596
863
|
const lower = text.toLowerCase();
|
|
597
864
|
if (["\uBC84\uADF8", "\uC624\uB958", "\uC548\uB428", "crash", "bug", "error", "broken"].some((w) => lower.includes(w))) return "bug_report";
|
|
@@ -602,103 +869,97 @@ function detectSentiment(text) {
|
|
|
602
869
|
}
|
|
603
870
|
async function generateReply(opts) {
|
|
604
871
|
const client = new Anthropic2({ apiKey: process.env.ANTHROPIC_API_KEY });
|
|
872
|
+
const m = M4();
|
|
873
|
+
const toneGuides = m.toneGuides;
|
|
874
|
+
const sentimentPrompts = m.sentimentPrompts;
|
|
875
|
+
const localeNames = m.localeNames;
|
|
605
876
|
const sentiment = detectSentiment(opts.text);
|
|
606
|
-
const toneGuide =
|
|
607
|
-
const sentimentPrompt =
|
|
608
|
-
const stars = opts.rating !== void 0 ?
|
|
609
|
-
|
|
610
|
-
const LOCALE_NAMES = { ko: "\uD55C\uAD6D\uC5B4", en: "\uC601\uC5B4", ja: "\uC77C\uBCF8\uC5B4", "en-US": "\uC601\uC5B4", "zh-TW": "\uBC88\uCCB4\uC911\uAD6D\uC5B4" };
|
|
611
|
-
const langName = LOCALE_NAMES[opts.language] ?? opts.language;
|
|
877
|
+
const toneGuide = toneGuides[opts.tone] ?? toneGuides.friendly;
|
|
878
|
+
const sentimentPrompt = sentimentPrompts[sentiment] ?? sentimentPrompts.neutral;
|
|
879
|
+
const stars = opts.rating !== void 0 ? m.starsLabel(`${"\u2605".repeat(opts.rating)}${"\u2606".repeat(5 - opts.rating)}`, opts.rating) : "";
|
|
880
|
+
const langName = localeNames[opts.language] ?? opts.language;
|
|
612
881
|
const response = await client.messages.create({
|
|
613
882
|
model: "claude-haiku-4-5-20251001",
|
|
614
883
|
max_tokens: 500,
|
|
615
|
-
system:
|
|
884
|
+
system: m.system(langName, toneGuide, opts.developerName ?? m.defaultDeveloper),
|
|
616
885
|
messages: [{
|
|
617
886
|
role: "user",
|
|
618
|
-
content:
|
|
619
|
-
${stars}\uB9AC\uBDF0: "${opts.text}"
|
|
620
|
-
|
|
621
|
-
\uC9C0\uCE68: ${sentimentPrompt}
|
|
622
|
-
|
|
623
|
-
JSON\uC73C\uB85C\uB9CC \uC751\uB2F5: { "reply": "\uB2F5\uBCC0 \uD14D\uC2A4\uD2B8" }`
|
|
887
|
+
content: m.userPrompt(opts.appName ?? m.defaultApp, stars, opts.text, sentimentPrompt)
|
|
624
888
|
}]
|
|
625
889
|
});
|
|
626
890
|
const raw = response.content[0].type === "text" ? response.content[0].text : "";
|
|
627
891
|
const match = raw.match(/\{[\s\S]*\}/);
|
|
628
|
-
if (!match) throw new Error(
|
|
892
|
+
if (!match) throw new Error(m.parseFailed);
|
|
629
893
|
const parsed = JSON.parse(match[0]);
|
|
630
894
|
return parsed.reply;
|
|
631
895
|
}
|
|
632
896
|
async function cmdReview(argv) {
|
|
633
897
|
const args = parseArgs3(argv);
|
|
634
|
-
process.stdout.write(kleur4.bold(
|
|
898
|
+
process.stdout.write(kleur4.bold(M4().title));
|
|
635
899
|
if (!process.env.ANTHROPIC_API_KEY) {
|
|
636
|
-
process.stdout.write(kleur4.red(
|
|
637
|
-
process.stdout.write(kleur4.dim(
|
|
900
|
+
process.stdout.write(kleur4.red(M4().noApiKey));
|
|
901
|
+
process.stdout.write(kleur4.dim(M4().noApiKeyHint));
|
|
638
902
|
process.exit(1);
|
|
639
903
|
}
|
|
640
904
|
let reviewText = args.text;
|
|
641
905
|
if (!reviewText) {
|
|
642
906
|
if (args.noInteractive) {
|
|
643
|
-
process.stdout.write(kleur4.red(
|
|
907
|
+
process.stdout.write(kleur4.red(M4().textRequired));
|
|
644
908
|
process.exit(1);
|
|
645
909
|
}
|
|
646
|
-
process.stdout.write(kleur4.dim(
|
|
910
|
+
process.stdout.write(kleur4.dim(M4().enterReview));
|
|
647
911
|
reviewText = await promptUser2("> ");
|
|
648
912
|
if (!reviewText) {
|
|
649
|
-
process.stdout.write(kleur4.yellow(
|
|
913
|
+
process.stdout.write(kleur4.yellow(M4().noInput));
|
|
650
914
|
process.exit(0);
|
|
651
915
|
}
|
|
652
916
|
}
|
|
653
917
|
if (args.rating !== void 0) {
|
|
654
918
|
const stars = "\u2605".repeat(args.rating) + "\u2606".repeat(5 - args.rating);
|
|
655
|
-
process.stdout.write(kleur4.dim(
|
|
656
|
-
|
|
657
|
-
`));
|
|
919
|
+
process.stdout.write(kleur4.dim(M4().meta(stars, args.tone, args.language)));
|
|
658
920
|
}
|
|
659
|
-
process.stdout.write(
|
|
921
|
+
process.stdout.write(M4().generating);
|
|
660
922
|
const reply = await generateReply({ ...args, text: reviewText });
|
|
661
|
-
process.stdout.write("\n" + kleur4.bold(
|
|
923
|
+
process.stdout.write("\n" + kleur4.bold(M4().hdrReply));
|
|
662
924
|
process.stdout.write(reply + "\n");
|
|
663
|
-
process.stdout.write(kleur4.dim(
|
|
925
|
+
process.stdout.write(kleur4.dim(M4().draftWarning));
|
|
664
926
|
const shouldPrompt = !args.apply && !args.noInteractive && process.stdout.isTTY;
|
|
665
927
|
if (!args.apply && !shouldPrompt) return;
|
|
666
928
|
let doApply = args.apply;
|
|
667
929
|
if (shouldPrompt) {
|
|
668
|
-
const ans = await promptUser2(
|
|
930
|
+
const ans = await promptUser2(M4().postPrompt);
|
|
669
931
|
doApply = ans.toLowerCase() === "y";
|
|
670
932
|
}
|
|
671
933
|
if (!doApply) {
|
|
672
|
-
process.stdout.write(kleur4.dim(
|
|
934
|
+
process.stdout.write(kleur4.dim(M4().skipped));
|
|
673
935
|
return;
|
|
674
936
|
}
|
|
675
937
|
const cfg = await getEffectiveConfig();
|
|
676
938
|
if (!cfg) {
|
|
677
|
-
process.stdout.write(kleur4.yellow(
|
|
939
|
+
process.stdout.write(kleur4.yellow(M4().needAccount));
|
|
678
940
|
return;
|
|
679
941
|
}
|
|
680
942
|
let reviewId = args.reviewId;
|
|
681
943
|
let packageName = args.packageName;
|
|
682
944
|
if (!reviewId || !packageName) {
|
|
683
945
|
if (args.noInteractive) {
|
|
684
|
-
process.stdout.write(kleur4.red(
|
|
946
|
+
process.stdout.write(kleur4.red(M4().idsRequired));
|
|
685
947
|
process.exit(1);
|
|
686
948
|
}
|
|
687
|
-
if (!packageName) packageName = await promptUser2(
|
|
688
|
-
if (!reviewId) reviewId = await promptUser2(
|
|
949
|
+
if (!packageName) packageName = await promptUser2(M4().packagePrompt);
|
|
950
|
+
if (!reviewId) reviewId = await promptUser2(M4().reviewIdPrompt);
|
|
689
951
|
}
|
|
690
952
|
if (!reviewId || !packageName) {
|
|
691
|
-
process.stdout.write(kleur4.yellow(
|
|
953
|
+
process.stdout.write(kleur4.yellow(M4().notEnoughInfo));
|
|
692
954
|
return;
|
|
693
955
|
}
|
|
694
|
-
process.stdout.write(
|
|
956
|
+
process.stdout.write(M4().posting);
|
|
695
957
|
const r = await mcpCall(cfg.endpoint, cfg.token, "playstore_reply_review", {
|
|
696
958
|
package_name: packageName,
|
|
697
959
|
review_id: reviewId,
|
|
698
960
|
reply_text: reply
|
|
699
961
|
});
|
|
700
|
-
process.stdout.write(r.isError ? kleur4.red(
|
|
701
|
-
`) : kleur4.green("\u2713 \uB2F5\uBCC0 \uAC8C\uC2DC \uC644\uB8CC\n"));
|
|
962
|
+
process.stdout.write(r.isError ? kleur4.red(M4().postFailed(r.text)) : kleur4.green(M4().posted));
|
|
702
963
|
}
|
|
703
964
|
|
|
704
965
|
// src/auth.ts
|
|
@@ -706,8 +967,9 @@ import kleur5 from "kleur";
|
|
|
706
967
|
function log(msg) {
|
|
707
968
|
process.stdout.write(msg + "\n");
|
|
708
969
|
}
|
|
709
|
-
|
|
710
|
-
|
|
970
|
+
var M5 = catalog(
|
|
971
|
+
{
|
|
972
|
+
help: `${kleur5.bold("mimi-seed auth")} \u2014 \uB85C\uCEEC \uC790\uACA9\uC99D\uBA85 \uC778\uC99D/\uAD00\uB9AC
|
|
711
973
|
|
|
712
974
|
${kleur5.bold("Google OAuth (Firebase / AdMob / Play):")}
|
|
713
975
|
${kleur5.cyan("mimi-seed auth login")} \uBE0C\uB77C\uC6B0\uC800\uB85C \uB85C\uADF8\uC778 (\uC774\uBBF8 \uC788\uC73C\uBA74 \uC790\uB3D9 refresh \uC2DC\uB3C4)
|
|
@@ -738,7 +1000,47 @@ ${kleur5.bold("login \uC635\uC158:")}
|
|
|
738
1000
|
--timeout <\uCD08> \uCF5C\uBC31 \uB300\uAE30 \uC2DC\uAC04 (\uAE30\uBCF8 600)
|
|
739
1001
|
--force \uAE30\uC874 \uD1A0\uD070 \uBB34\uC2DC\uD558\uACE0 \uAC15\uC81C \uC7AC\uB85C\uADF8\uC778
|
|
740
1002
|
|
|
741
|
-
${kleur5.dim(`\uB0B4\uBD80\uC801\uC73C\uB85C ${MCP_PKG} \uC758 mimi-seed-*-auth CLI\uB97C \uD638\uCD9C\uD569\uB2C8\uB2E4.`)}
|
|
1003
|
+
${kleur5.dim(`\uB0B4\uBD80\uC801\uC73C\uB85C ${MCP_PKG} \uC758 mimi-seed-*-auth CLI\uB97C \uD638\uCD9C\uD569\uB2C8\uB2E4.`)}`,
|
|
1004
|
+
connectAll: "\n \uD55C \uBC88\uC5D0 \uC5F0\uACB0: mimi-seed setup"
|
|
1005
|
+
},
|
|
1006
|
+
{
|
|
1007
|
+
help: `${kleur5.bold("mimi-seed auth")} \u2014 local credential setup
|
|
1008
|
+
|
|
1009
|
+
${kleur5.bold("Google OAuth (Firebase / AdMob / Play):")}
|
|
1010
|
+
${kleur5.cyan("mimi-seed auth login")} sign in via browser (refreshes an existing token if it can)
|
|
1011
|
+
${kleur5.cyan("mimi-seed auth status")} current OAuth token status
|
|
1012
|
+
${kleur5.cyan("mimi-seed auth refresh")} refresh only, using refresh_token (no browser)
|
|
1013
|
+
${kleur5.cyan("mimi-seed auth logout")} delete the OAuth token
|
|
1014
|
+
|
|
1015
|
+
${kleur5.bold("Per-platform credentials:")}
|
|
1016
|
+
${kleur5.cyan("mimi-seed auth appstore")} App Store Connect API key (appstore.json)
|
|
1017
|
+
${kleur5.cyan("mimi-seed auth playstore")} register a Play service-account JSON
|
|
1018
|
+
${kleur5.cyan("mimi-seed auth bigquery")} BigQuery service account (Crashlytics export, etc.)
|
|
1019
|
+
|
|
1020
|
+
${kleur5.bold("Build / marketing:")}
|
|
1021
|
+
${kleur5.cyan("mimi-seed auth jenkins")} Jenkins connection (jenkins.json)
|
|
1022
|
+
${kleur5.cyan("mimi-seed auth ci")} GitHub Actions / GitLab CI (ci.json)
|
|
1023
|
+
${kleur5.cyan("mimi-seed auth googleads")} Google Ads (google-ads.json)
|
|
1024
|
+
${kleur5.cyan("mimi-seed auth facebook")} Facebook Page
|
|
1025
|
+
${kleur5.cyan("mimi-seed auth instagram")} Instagram
|
|
1026
|
+
|
|
1027
|
+
${kleur5.bold("Everything at a glance:")}
|
|
1028
|
+
${kleur5.cyan("mimi-seed auth status --all")} which credentials you have
|
|
1029
|
+
|
|
1030
|
+
${kleur5.bold("Connect them all in one pass:")}
|
|
1031
|
+
${kleur5.cyan("mimi-seed setup")} guided, one credential at a time (recommended)
|
|
1032
|
+
|
|
1033
|
+
${kleur5.bold("login options:")}
|
|
1034
|
+
--no-browser don't open the URL automatically (paste it yourself)
|
|
1035
|
+
--timeout <sec> how long to wait for the callback (default 600)
|
|
1036
|
+
--force ignore the existing token and sign in again
|
|
1037
|
+
|
|
1038
|
+
${kleur5.dim(`Under the hood this calls the mimi-seed-*-auth CLIs from ${MCP_PKG}.`)}`,
|
|
1039
|
+
connectAll: "\n Connect everything at once: mimi-seed setup"
|
|
1040
|
+
}
|
|
1041
|
+
);
|
|
1042
|
+
function printAuthHelp() {
|
|
1043
|
+
log(M5().help);
|
|
742
1044
|
}
|
|
743
1045
|
function printAllCredStatus() {
|
|
744
1046
|
log(kleur5.bold(t().auth.statusTitle + " ") + kleur5.dim("(~/.mimi-seed)"));
|
|
@@ -749,7 +1051,7 @@ function printAllCredStatus() {
|
|
|
749
1051
|
const tail = d.present ? kleur5.dim(d.detail ?? "") : kleur5.dim(`\u2192 ${spec.fix}`);
|
|
750
1052
|
log(` ${mark} ${credLabel(spec).padEnd(24)} ${tail}`);
|
|
751
1053
|
}
|
|
752
|
-
log(kleur5.dim(
|
|
1054
|
+
log(kleur5.dim(M5().connectAll));
|
|
753
1055
|
}
|
|
754
1056
|
async function cmdAuth(args) {
|
|
755
1057
|
const sub = args[0];
|
|
@@ -770,7 +1072,7 @@ async function cmdAuth(args) {
|
|
|
770
1072
|
if (sub === "facebook") return void exitWith(await runMcpBin("mimi-seed-social-auth", ["facebook"]));
|
|
771
1073
|
if (sub === "instagram") return void exitWith(await runMcpBin("mimi-seed-social-auth", ["instagram"]));
|
|
772
1074
|
if (sub === "ci") {
|
|
773
|
-
const { cmdSetup: cmdSetup2 } = await import("./setup-
|
|
1075
|
+
const { cmdSetup: cmdSetup2 } = await import("./setup-NQHLA3AJ.js");
|
|
774
1076
|
await cmdSetup2(["--only", "github,gitlab", "--reconnect", "github,gitlab"]);
|
|
775
1077
|
return;
|
|
776
1078
|
}
|
|
@@ -837,9 +1139,7 @@ async function runMcpBin2(bin, extraArgs) {
|
|
|
837
1139
|
shell: true
|
|
838
1140
|
});
|
|
839
1141
|
child.on("error", (e) => {
|
|
840
|
-
process.stderr.write(
|
|
841
|
-
\u274C npx \uC2E4\uD589 \uC2E4\uD328: ${e.message}
|
|
842
|
-
`);
|
|
1142
|
+
process.stderr.write(t().auth.npxFailed("npx", e.message));
|
|
843
1143
|
resolve(1);
|
|
844
1144
|
});
|
|
845
1145
|
child.on("exit", (code) => resolve(code ?? 0));
|
|
@@ -867,6 +1167,42 @@ import kleur7 from "kleur";
|
|
|
867
1167
|
function log3(msg) {
|
|
868
1168
|
process.stdout.write(msg + "\n");
|
|
869
1169
|
}
|
|
1170
|
+
var M6 = catalog(
|
|
1171
|
+
{
|
|
1172
|
+
killedPid: (pid) => ` PID ${pid} \uC885\uB8CC`,
|
|
1173
|
+
title: (server) => `MCP \uC11C\uBC84 \uC7AC\uC2DC\uC791: ${server}`,
|
|
1174
|
+
none: "(\uC5C6\uC74C)",
|
|
1175
|
+
notFound: (server) => `'${server}' \uC11C\uBC84\uB97C ~/.claude/.claude.json\uC5D0\uC11C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.`,
|
|
1176
|
+
registered: (list) => ` \uB4F1\uB85D\uB41C \uC11C\uBC84: ${list}`,
|
|
1177
|
+
httpServer: (server) => `'${server}'\uB294 HTTP/SSE \uC11C\uBC84\uC785\uB2C8\uB2E4. \uD504\uB85C\uC138\uC2A4 \uC7AC\uC2DC\uC791\uC774 \uD544\uC694\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.`,
|
|
1178
|
+
httpHint: " Claude Code\uC5D0\uC11C /mcp \uB97C \uC2E4\uD589\uD574 \uC5F0\uACB0 \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
1179
|
+
noMarker: "\uD504\uB85C\uC138\uC2A4 \uC2DD\uBCC4\uC790(\uC2A4\uD06C\uB9BD\uD2B8 \uACBD\uB85C)\uB97C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
1180
|
+
configLine: (cfg) => ` \uC124\uC815: ${cfg}`,
|
|
1181
|
+
markerLine: (marker) => ` \uC2DD\uBCC4\uC790: ${marker}`,
|
|
1182
|
+
noProcess: "\u26A0 \uC2E4\uD589 \uC911\uC778 \uD504\uB85C\uC138\uC2A4\uB97C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
1183
|
+
noProcessHint: " \uC774\uBBF8 \uC885\uB8CC\uB410\uAC70\uB098, Claude Code\uAC00 \uC544\uC9C1 \uC11C\uBC84\uB97C \uC2DC\uC791\uD558\uC9C0 \uC54A\uC740 \uC0C1\uD0DC\uC77C \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
1184
|
+
killed: (server, n) => `\u2713 ${server} \uC885\uB8CC\uB428 (${n}\uAC1C \uD504\uB85C\uC138\uC2A4)`,
|
|
1185
|
+
killedHint: " Claude Code\uAC00 \uB2E4\uC74C \uB3C4\uAD6C \uD638\uCD9C \uC2DC \uC790\uB3D9\uC73C\uB85C \uC7AC\uC5F0\uACB0\uD569\uB2C8\uB2E4.",
|
|
1186
|
+
verify: " \uC5F0\uACB0 \uD655\uC778: Claude Code\uC5D0\uC11C /mcp \uC2E4\uD589"
|
|
1187
|
+
},
|
|
1188
|
+
{
|
|
1189
|
+
killedPid: (pid) => ` PID ${pid} killed`,
|
|
1190
|
+
title: (server) => `Restarting MCP server: ${server}`,
|
|
1191
|
+
none: "(none)",
|
|
1192
|
+
registered: (list) => ` Registered servers: ${list}`,
|
|
1193
|
+
notFound: (server) => `Could not find the '${server}' server in ~/.claude/.claude.json.`,
|
|
1194
|
+
httpServer: (server) => `'${server}' is an HTTP/SSE server. It does not need a process restart.`,
|
|
1195
|
+
httpHint: " Run /mcp in Claude Code to check the connection.",
|
|
1196
|
+
noMarker: "Could not find a process marker (script path).",
|
|
1197
|
+
configLine: (cfg) => ` Config: ${cfg}`,
|
|
1198
|
+
markerLine: (marker) => ` Marker: ${marker}`,
|
|
1199
|
+
noProcess: "\u26A0 No running process found.",
|
|
1200
|
+
noProcessHint: " It may have already exited, or Claude Code may not have started the server yet.",
|
|
1201
|
+
killed: (server, n) => `\u2713 ${server} killed (${n} process(es))`,
|
|
1202
|
+
killedHint: " Claude Code will reconnect automatically on the next tool call.",
|
|
1203
|
+
verify: " Verify the connection: run /mcp in Claude Code"
|
|
1204
|
+
}
|
|
1205
|
+
);
|
|
870
1206
|
function readClaudeJson() {
|
|
871
1207
|
const p = path2.join(os.homedir(), ".claude.json");
|
|
872
1208
|
try {
|
|
@@ -903,7 +1239,7 @@ function killByMarker(marker) {
|
|
|
903
1239
|
for (const pid of pids) {
|
|
904
1240
|
try {
|
|
905
1241
|
execSync2(`taskkill /F /PID ${pid}`, { stdio: "pipe" });
|
|
906
|
-
log3(kleur7.dim(
|
|
1242
|
+
log3(kleur7.dim(M6().killedPid(pid)));
|
|
907
1243
|
killed++;
|
|
908
1244
|
} catch {
|
|
909
1245
|
}
|
|
@@ -920,40 +1256,40 @@ function killByMarker(marker) {
|
|
|
920
1256
|
}
|
|
921
1257
|
async function cmdRestart(args) {
|
|
922
1258
|
const serverName = args[0] ?? "mimi-seed";
|
|
923
|
-
log3(kleur7.bold(
|
|
1259
|
+
log3(kleur7.bold(M6().title(serverName)));
|
|
924
1260
|
log3("");
|
|
925
1261
|
const d = readClaudeJson();
|
|
926
1262
|
const servers = d.mcpServers;
|
|
927
1263
|
const cfg = servers?.[serverName];
|
|
928
1264
|
if (!cfg) {
|
|
929
|
-
const available = servers ? Object.keys(servers).join(", ") :
|
|
930
|
-
log3(kleur7.red(
|
|
931
|
-
log3(kleur7.dim(
|
|
1265
|
+
const available = servers ? Object.keys(servers).join(", ") : M6().none;
|
|
1266
|
+
log3(kleur7.red(M6().notFound(serverName)));
|
|
1267
|
+
log3(kleur7.dim(M6().registered(available)));
|
|
932
1268
|
process.exit(1);
|
|
933
1269
|
}
|
|
934
1270
|
if (cfg.type === "http" || cfg.type === "sse") {
|
|
935
|
-
log3(kleur7.yellow(
|
|
936
|
-
log3(kleur7.dim(
|
|
1271
|
+
log3(kleur7.yellow(M6().httpServer(serverName)));
|
|
1272
|
+
log3(kleur7.dim(M6().httpHint));
|
|
937
1273
|
return;
|
|
938
1274
|
}
|
|
939
1275
|
const marker = findProcessMarker(cfg);
|
|
940
1276
|
if (!marker) {
|
|
941
|
-
log3(kleur7.yellow(
|
|
942
|
-
log3(kleur7.dim(
|
|
1277
|
+
log3(kleur7.yellow(M6().noMarker));
|
|
1278
|
+
log3(kleur7.dim(M6().configLine(JSON.stringify(cfg))));
|
|
943
1279
|
process.exit(1);
|
|
944
1280
|
}
|
|
945
|
-
log3(kleur7.dim(
|
|
1281
|
+
log3(kleur7.dim(M6().markerLine(marker)));
|
|
946
1282
|
const { killed } = killByMarker(marker);
|
|
947
1283
|
if (killed === 0) {
|
|
948
|
-
log3(kleur7.yellow(
|
|
949
|
-
log3(kleur7.dim(
|
|
1284
|
+
log3(kleur7.yellow(M6().noProcess));
|
|
1285
|
+
log3(kleur7.dim(M6().noProcessHint));
|
|
950
1286
|
} else {
|
|
951
1287
|
log3("");
|
|
952
|
-
log3(kleur7.green(
|
|
953
|
-
log3(kleur7.dim(
|
|
1288
|
+
log3(kleur7.green(M6().killed(serverName, killed)));
|
|
1289
|
+
log3(kleur7.dim(M6().killedHint));
|
|
954
1290
|
}
|
|
955
1291
|
log3("");
|
|
956
|
-
log3(kleur7.cyan(
|
|
1292
|
+
log3(kleur7.cyan(M6().verify));
|
|
957
1293
|
}
|
|
958
1294
|
|
|
959
1295
|
// src/mcp-config.ts
|
|
@@ -962,6 +1298,20 @@ import path3 from "path";
|
|
|
962
1298
|
import os2 from "os";
|
|
963
1299
|
import kleur8 from "kleur";
|
|
964
1300
|
var SERVER_NAME = "mimi-seed";
|
|
1301
|
+
var M7 = catalog(
|
|
1302
|
+
{
|
|
1303
|
+
claudeTitle: "Claude Code MCP \uB4F1\uB85D \u2014 \uC544\uB798 \uD55C \uC904\uC744 \uADF8\uB300\uB85C \uC2E4\uD589\uD558\uC138\uC694:",
|
|
1304
|
+
tokenWarning: (loc) => ` \u26A0 \uC2E4\uC81C \uD1A0\uD070\uC774 \uD3EC\uD568\uB41C \uBA85\uB839\uC785\uB2C8\uB2E4 (\uC178 \uD788\uC2A4\uD1A0\uB9AC\uC5D0 \uB0A8\uC74C). \uD1A0\uD070\uC740 ${loc} \uC5D0\uB3C4 \uC800\uC7A5\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4.`,
|
|
1305
|
+
codexTitle: "Codex MCP \uB4F1\uB85D:",
|
|
1306
|
+
codexManual: " # \uB610\uB294 \uC218\uB3D9\uC73C\uB85C ~/.codex/config.toml \uC5D0 [mcp_servers.mimi-seed] \uCD94\uAC00"
|
|
1307
|
+
},
|
|
1308
|
+
{
|
|
1309
|
+
claudeTitle: "Register the MCP server with Claude Code \u2014 run this single line as-is:",
|
|
1310
|
+
tokenWarning: (loc) => ` \u26A0 This command contains your real token (it lands in your shell history). The token is also stored in ${loc}.`,
|
|
1311
|
+
codexTitle: "Register with Codex:",
|
|
1312
|
+
codexManual: " # or add [mcp_servers.mimi-seed] to ~/.codex/config.toml by hand"
|
|
1313
|
+
}
|
|
1314
|
+
);
|
|
965
1315
|
function tomlString(value) {
|
|
966
1316
|
return JSON.stringify(value);
|
|
967
1317
|
}
|
|
@@ -992,13 +1342,13 @@ function claudeMcpAddCommand(cfg) {
|
|
|
992
1342
|
function printMcpSetup(cfg) {
|
|
993
1343
|
process.stdout.write(
|
|
994
1344
|
[
|
|
995
|
-
kleur8.bold(
|
|
1345
|
+
kleur8.bold(M7().claudeTitle),
|
|
996
1346
|
kleur8.cyan(` ${claudeMcpAddCommand(cfg)}`),
|
|
997
|
-
kleur8.dim(
|
|
1347
|
+
kleur8.dim(M7().tokenWarning(CONFIG_LOCATION_HINT)),
|
|
998
1348
|
"",
|
|
999
|
-
kleur8.dim(
|
|
1349
|
+
kleur8.dim(M7().codexTitle),
|
|
1000
1350
|
kleur8.dim(" mimi-seed mcp codex --write"),
|
|
1001
|
-
kleur8.dim(
|
|
1351
|
+
kleur8.dim(M7().codexManual)
|
|
1002
1352
|
].join("\n") + "\n"
|
|
1003
1353
|
);
|
|
1004
1354
|
}
|
|
@@ -1063,6 +1413,335 @@ async function ensureReleaseManifest(cwd) {
|
|
|
1063
1413
|
// src/index.ts
|
|
1064
1414
|
var DEFAULT_WEB_BASE = process.env.MIMI_SEED_WEB_BASE ?? "https://mimi-seed.pryzm.gg";
|
|
1065
1415
|
var DEFAULT_MCP_ENDPOINT = `${DEFAULT_WEB_BASE}/api/mcp`;
|
|
1416
|
+
var M8 = catalog(
|
|
1417
|
+
{
|
|
1418
|
+
noProjectSignal: "\u26A0 package.json / app.json / android / ios \uB97C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uADF8\uB798\uB3C4 \uC9C4\uD589\uD569\uB2C8\uB2E4.",
|
|
1419
|
+
detecting: "\u{1F50D} \uC571 \uAC10\uC9C0 \uC911...",
|
|
1420
|
+
noAppDetected: "\uAC10\uC9C0\uB41C \uC571 \uC5C6\uC74C. \uC6F9\uC5D0\uC11C \uC218\uB3D9 \uB4F1\uB85D \uAC00\uB2A5.",
|
|
1421
|
+
unnamed: "(\uC774\uB984 \uBBF8\uC0C1)",
|
|
1422
|
+
ciMode: "CI \uBAA8\uB4DC: MIMI_SEED_TOKEN \uC0AC\uC6A9",
|
|
1423
|
+
syncFailed: (text) => "\uB4F1\uB85D \uC2E4\uD328: " + text,
|
|
1424
|
+
manifest: (created) => ` \uB9B4\uB9AC\uC988 \uB178\uD2B8 SSOT: ${created ? "\uC0DD\uC131" : "\uD655\uC778"} docs/releases.json`,
|
|
1425
|
+
doneCi: "\u2713 \uC644\uB8CC (CI \uBAA8\uB4DC)",
|
|
1426
|
+
waitingLogin: "\u{1F510} \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uB85C\uADF8\uC778 \uB300\uAE30...",
|
|
1427
|
+
connectFailed: (msg) => "\uC5F0\uACB0 \uC2E4\uD328: " + msg,
|
|
1428
|
+
tokenReceived: "\u2713 \uD1A0\uD070 \uC218\uC2E0",
|
|
1429
|
+
saved: (location) => ` \uC800\uC7A5\uB428: ${location}`,
|
|
1430
|
+
registering: "\u{1F504} \uC571 \uB4F1\uB85D \uC911...",
|
|
1431
|
+
claudeAgent: " Claude \uC5D0\uC774\uC804\uD2B8 \uC124\uC815: .claude/mimi-seed.md",
|
|
1432
|
+
codexAgent: " Codex \uC5D0\uC774\uC804\uD2B8 \uC124\uC815: AGENTS.md",
|
|
1433
|
+
ready: "\u2713 \uC900\uBE44 \uC644\uB8CC.",
|
|
1434
|
+
askLike: "Claude Code \uB610\uB294 Codex\uC5D0\uC11C \uC774\uB807\uAC8C \uBB3C\uC5B4\uBCF4\uC138\uC694:",
|
|
1435
|
+
ask1: ' "\uB0B4 \uC571 \uCD9C\uC2DC \uC900\uBE44\uB410\uC5B4?"',
|
|
1436
|
+
ask2: ' "\uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC368\uC918"',
|
|
1437
|
+
ask3: ' "\uB4F1\uB85D\uB41C \uC571 \uBAA9\uB85D \uBCF4\uC5EC\uC918"',
|
|
1438
|
+
dashboard: (url) => `\uB300\uC2DC\uBCF4\uB4DC: ${url}`,
|
|
1439
|
+
localTitle: "\u2500\u2500 \uB85C\uCEEC MCP \uCD94\uAC00 \uC124\uC815 (--local) \u2500\u2500",
|
|
1440
|
+
localIntro: "\uC6D0\uACA9 MCP(PAT, \uC77D\uAE30\xB7\uC9C4\uB2E8)\uB294 \uC704\uC5D0\uC11C \uB05D. \uB85C\uCEEC MCP\uB294 Google OAuth\uB85C \uC2A4\uD1A0\uC5B4 \uC4F0\uAE30 \uB3C4\uAD6C \uC804\uCCB4\uB97C \uC9C1\uC811 \uC2E4\uD589\uD569\uB2C8\uB2E4 (Node 20+).",
|
|
1441
|
+
localStep1: "1) Google \uB85C\uADF8\uC778 (Firebase / AdMob / Play / Ads):",
|
|
1442
|
+
localStep2: "2) \uB85C\uCEEC MCP \uC11C\uBC84 \uB4F1\uB85D (\uC6D0\uACA9 'mimi-seed' \uC640 \uBCC4\uAC1C):",
|
|
1443
|
+
localCodexHint: ' Codex: ~/.codex/config.toml \uC5D0 [mcp_servers.mimi-seed-local] command="npx", args=["-y","@yoonion/mimi-seed-mcp"]',
|
|
1444
|
+
localStep3: "3) \uB098\uBA38\uC9C0 \uACC4\uC815 \uC5F0\uACB0 (App Store / Play / Jenkins / CI / \uC18C\uC15C \u2026):",
|
|
1445
|
+
localSetupHint: " \uAC01 \uD56D\uBAA9\uC5D0\uC11C [?] \uB97C \uB204\uB974\uBA74 \uD1A0\uD070 \uBC1C\uAE09 \uBC29\uBC95\uC744 \uC54C\uB824\uC90D\uB2C8\uB2E4.",
|
|
1446
|
+
notConnected: "\uC5F0\uACB0\uB41C Mimi Seed \uACC4\uC815\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. `mimi-seed init` \uC2E4\uD589.",
|
|
1447
|
+
statusTitle: "Mimi Seed \uC5F0\uACB0 \uC0C1\uD0DC",
|
|
1448
|
+
statusToken: (prefix, date) => ` \uD1A0\uD070: ${prefix}\u2026 (${date})`,
|
|
1449
|
+
statusEndpoint: (endpoint) => ` \uC5D4\uB4DC\uD3EC\uC778\uD2B8: ${endpoint}`,
|
|
1450
|
+
appList: "\u{1F4CB} \uC571 \uBAA9\uB85D:",
|
|
1451
|
+
listFailed: (text) => "\uC870\uD68C \uC2E4\uD328: " + text,
|
|
1452
|
+
logoutDone: "\u2713 \uB85C\uCEEC \uC124\uC815 \uC0AD\uC81C \uC644\uB8CC.",
|
|
1453
|
+
logoutRevoke: "\uC6F9\uC5D0\uC11C \uD1A0\uD070 \uD574\uC9C0: /workspace/api-tokens",
|
|
1454
|
+
codexWritten: "\u2713 Codex MCP \uC124\uC815 \uC644\uB8CC",
|
|
1455
|
+
codexWriteWarn: " \u26A0 config.toml\uC5D0 \uC2E4\uC81C \uD1A0\uD070\uC774 \uD3C9\uBB38\uC73C\uB85C \uC800\uC7A5\uB429\uB2C8\uB2E4 (\uD30C\uC77C \uAD8C\uD55C \uD655\uC778 \uAD8C\uC7A5).",
|
|
1456
|
+
codexVerify: "Codex\uB97C \uC0C8\uB85C \uC5F4\uACE0 `/mcp` \uB610\uB294 `codex mcp list`\uB85C \uD655\uC778\uD558\uC138\uC694.",
|
|
1457
|
+
codexTitle: "Codex MCP \uB4F1\uB85D",
|
|
1458
|
+
codexAuto: "\uC790\uB3D9 \uB4F1\uB85D:",
|
|
1459
|
+
codexManual: "\uC218\uB3D9 \uB4F1\uB85D \uC608\uC2DC (~/.codex/config.toml) \u2014 \uC2E4\uC81C \uD1A0\uD070 \uD3EC\uD568:",
|
|
1460
|
+
claudeTitle: "Claude Code MCP \uB4F1\uB85D \u2014 \uC544\uB798 \uD55C \uC904\uC744 \uADF8\uB300\uB85C \uC2E4\uD589\uD558\uC138\uC694:",
|
|
1461
|
+
claudeWarn: " \u26A0 \uC2E4\uC81C \uD1A0\uD070\uC774 \uD3EC\uD568\uB41C \uBA85\uB839\uC785\uB2C8\uB2E4 (\uC178 \uD788\uC2A4\uD1A0\uB9AC\uC5D0 \uB0A8\uC74C). \uD1A0\uD070\uC740 ~/.mimi-seed/config.json \uC5D0\uB3C4 \uC800\uC7A5\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
1462
|
+
// 명령별 상세 사용법 (SSOT). `mimi-seed <command> --help` 와 overview 가 공유.
|
|
1463
|
+
usage: {
|
|
1464
|
+
init: `${kleur9.bold("mimi-seed init")} \u2014 \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8\uB97C Mimi Seed\uC5D0 \uC5F0\uACB0
|
|
1465
|
+
|
|
1466
|
+
\uC571 \uC790\uB3D9 \uAC10\uC9C0(Expo/Gradle/Info.plist/pbxproj) \u2192 \uBE0C\uB77C\uC6B0\uC800 PAT \uBC1C\uAE09(\uC6D0\uACA9 MCP) \u2192 \uC571 \uB4F1\uB85D
|
|
1467
|
+
+ .claude/mimi-seed.md, AGENTS.md, docs/releases.json \uC0DD\uC131/\uD655\uC778.
|
|
1468
|
+
|
|
1469
|
+
\uC635\uC158:
|
|
1470
|
+
--local \uCD94\uAC00\uB85C Google OAuth \uB85C\uADF8\uC778 + \uB85C\uCEEC MCP(\uC2A4\uD1A0\uC5B4 \uC4F0\uAE30 \uB3C4\uAD6C \uC804\uCCB4) \uB4F1\uB85D \uC548\uB0B4`,
|
|
1471
|
+
setup: `${kleur9.bold("mimi-seed setup")} \u2014 \uAC00\uC9C4 \uACC4\uC815\uC744 \uD55C \uBC88\uC5D0 \uC5F0\uACB0 (\uC548\uB0B4\uD615 \uB9C8\uBC95\uC0AC)
|
|
1472
|
+
|
|
1473
|
+
\uC5F0\uACB0 \uC0C1\uD0DC\uB97C \uBA3C\uC800 \uBCF4\uC5EC\uC8FC\uACE0, \uC544\uC9C1 \uC5F0\uACB0\uB418\uC9C0 \uC54A\uC740 \uAC83\uB9CC \uC21C\uC11C\uB300\uB85C \uBB3C\uC5B4\uBCF8\uB2E4.
|
|
1474
|
+
\uAC01 \uD56D\uBAA9\uC5D0\uC11C [?] \uB97C \uB204\uB974\uBA74 "\uADF8 \uD1A0\uD070\uC744 \uC5B4\uB514\uC11C \uC5B4\uB5BB\uAC8C \uBC1C\uAE09\uBC1B\uB294\uC9C0"\uB97C \uC54C\uB824\uC900\uB2E4.
|
|
1475
|
+
\uC774\uBBF8 \uC5F0\uACB0\uB41C \uD56D\uBAA9\uC740 \uAC74\uB108\uB6F0\uBBC0\uB85C, \uC911\uAC04\uC5D0 \uADF8\uB9CC\uB450\uACE0 \uB098\uC911\uC5D0 \uB2E4\uC2DC \uC2E4\uD589\uD574\uB3C4 \uB41C\uB2E4.
|
|
1476
|
+
|
|
1477
|
+
\uC635\uC158:
|
|
1478
|
+
--only <ids> \uC9C0\uC815\uD55C \uC790\uACA9\uC99D\uBA85\uB9CC (\uC27C\uD45C \uAD6C\uBD84: oauth,appstore,jenkins \u2026)
|
|
1479
|
+
--reconnect <ids> \uC774\uBBF8 \uC5F0\uACB0\uB3FC \uC788\uC5B4\uB3C4 \uB2E4\uC2DC \uC124\uC815
|
|
1480
|
+
--platform android,ios \uD50C\uB7AB\uD3FC \uAC15\uC81C \uC9C0\uC815 (\uAE30\uBCF8: \uD504\uB85C\uC81D\uD2B8\uC5D0\uC11C \uC790\uB3D9 \uAC10\uC9C0)
|
|
1481
|
+
--yes, -y \uC544\uBB34\uAC83\uB3C4 \uBB3B\uC9C0 \uC54A\uACE0 \uC0C1\uD0DC\uD45C\uB9CC \uCD9C\uB825
|
|
1482
|
+
--non-interactive \uC704\uC640 \uB3D9\uC77C (CI \uC6A9)
|
|
1483
|
+
--fail-on-missing \uD544\uC218 \uC790\uACA9\uC99D\uBA85\uC774 \uC5C6\uC73C\uBA74 exit 1 (CI \uAC8C\uC774\uD2B8)
|
|
1484
|
+
|
|
1485
|
+
${kleur9.dim("\uBE44TTY / CI \uD658\uACBD\uC5D0\uC11C\uB294 \uD504\uB86C\uD504\uD2B8 \uC5C6\uC774 \uC0C1\uD0DC\uD45C\uB9CC \uCD9C\uB825\uD55C\uB2E4.")}`,
|
|
1486
|
+
lang: `${kleur9.bold("mimi-seed lang")} \u2014 CLI \uCD9C\uB825 \uC5B8\uC5B4 (\uD55C\uAD6D\uC5B4 / English)
|
|
1487
|
+
|
|
1488
|
+
mimi-seed lang \uD604\uC7AC \uC5B8\uC5B4 \uD45C\uC2DC
|
|
1489
|
+
mimi-seed lang ko \uD55C\uAD6D\uC5B4 (\uAE30\uBCF8)
|
|
1490
|
+
mimi-seed lang en English
|
|
1491
|
+
|
|
1492
|
+
${kleur9.dim("~/.mimi-seed/settings.json \uC5D0 \uC800\uC7A5\uB429\uB2C8\uB2E4. \uD658\uACBD\uBCC0\uC218 MIMI_SEED_LANG \uAC00 \uC788\uC73C\uBA74 \uADF8\uAC8C \uC6B0\uC120\uD569\uB2C8\uB2E4.")}
|
|
1493
|
+
${kleur9.dim("setup \uB9C8\uBC95\uC0AC\uAC00 \uCCAB \uC2E4\uD589 \uB54C \uBB3C\uC5B4\uBCF4\uBBC0\uB85C \uBCF4\uD1B5\uC740 \uC9C1\uC811 \uCE60 \uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.")}`,
|
|
1494
|
+
status: `${kleur9.bold("mimi-seed status")} \u2014 \uC5F0\uACB0 \uC0C1\uD0DC + \uB4F1\uB85D \uC571 \uBAA9\uB85D. \uC635\uC158 \uC5C6\uC74C.`,
|
|
1495
|
+
doctor: `${kleur9.bold("mimi-seed doctor")} \u2014 \uD658\uACBD \uC9C4\uB2E8 (\uD1A0\uD070\xB7Node\xB7Git\xB7\uD504\uB85C\uC81D\uD2B8\xB7CI). \uC635\uC158 \uC5C6\uC74C.`,
|
|
1496
|
+
logout: `${kleur9.bold("mimi-seed logout")} \u2014 \uB85C\uCEEC \uC124\uC815(config.json) \uC0AD\uC81C. \uC635\uC158 \uC5C6\uC74C.`,
|
|
1497
|
+
restart: `${kleur9.bold("mimi-seed restart")} \u2014 MCP \uC11C\uBC84 \uD504\uB85C\uC138\uC2A4 \uC7AC\uC2DC\uC791 (\uAE30\uBCF8: mimi-seed)
|
|
1498
|
+
|
|
1499
|
+
mimi-seed restart [server-name]`,
|
|
1500
|
+
notes: `${kleur9.bold("mimi-seed notes")} \u2014 \uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC0DD\uC131 (git log \u2192 AI \u2192 \uB9C8\uCF13 \uC801\uC6A9)
|
|
1501
|
+
|
|
1502
|
+
\uC635\uC158:
|
|
1503
|
+
--from <ref> \uC2DC\uC791 \uCEE4\uBC0B/\uD0DC\uADF8 (\uAE30\uBCF8: \uCD5C\uC2E0 \uD0DC\uADF8)
|
|
1504
|
+
--to <ref> \uB05D \uCEE4\uBC0B (\uAE30\uBCF8: HEAD)
|
|
1505
|
+
--locale ko,en-US \uB300\uC0C1 \uB85C\uCF00\uC77C (\uC27C\uD45C \uAD6C\uBD84)
|
|
1506
|
+
--apply \uC0DD\uC131 \uD6C4 \uC2A4\uD1A0\uC5B4\uC5D0 \uBC14\uB85C \uC801\uC6A9
|
|
1507
|
+
--no-interactive CI \uBAA8\uB4DC (\uD504\uB86C\uD504\uD2B8 \uC5C6\uC74C)
|
|
1508
|
+
--limit <n> \uCD5C\uB300 \uCEE4\uBC0B \uC218 (\uAE30\uBCF8: 30)`,
|
|
1509
|
+
check: `${kleur9.bold("mimi-seed check")} \u2014 \uCD9C\uC2DC \uC804 Readiness \uC810\uAC80
|
|
1510
|
+
|
|
1511
|
+
\uC635\uC158:
|
|
1512
|
+
--app <id> \uC571 ID \uC9C0\uC815
|
|
1513
|
+
--fail-on-blocker \uBE14\uB85C\uCEE4 \uC788\uC73C\uBA74 exit 1 (CI\uC6A9)`,
|
|
1514
|
+
review: `${kleur9.bold("mimi-seed review")} \u2014 \uB9AC\uBDF0 \uB2F5\uBCC0 AI \uCD08\uC548 \uC0DD\uC131 \uBC0F Play Store \uAC8C\uC2DC
|
|
1515
|
+
|
|
1516
|
+
\uC635\uC158:
|
|
1517
|
+
--text <\uB0B4\uC6A9> \uB9AC\uBDF0 \uC6D0\uBB38 (\uBBF8\uC785\uB825 \uC2DC \uB300\uD654\uD615 \uD504\uB86C\uD504\uD2B8)
|
|
1518
|
+
--rating <1-5> \uBCC4\uC810
|
|
1519
|
+
--tone <tone> friendly / professional / empathetic / brief (\uAE30\uBCF8: friendly)
|
|
1520
|
+
--language <\uCF54\uB4DC> \uB2F5\uBCC0 \uC5B8\uC5B4 (\uAE30\uBCF8: ko)
|
|
1521
|
+
--app-name <\uC774\uB984> \uC571 \uC774\uB984 (\uB9E5\uB77D\uC6A9)
|
|
1522
|
+
--apply \uB2F5\uBCC0\uC744 Play Store\uC5D0 \uAC8C\uC2DC
|
|
1523
|
+
--review-id <id> \uB9AC\uBDF0 ID (--apply \uC2DC \uD544\uC694)
|
|
1524
|
+
--package-name <p> \uD328\uD0A4\uC9C0\uBA85 (--apply \uC2DC \uD544\uC694)
|
|
1525
|
+
--no-interactive CI \uBAA8\uB4DC`,
|
|
1526
|
+
deploy: `${kleur9.bold("mimi-seed deploy")} \u2014 \uC571 \uC790\uB3D9 \uBC30\uD3EC (CI \uBE4C\uB4DC \u2192 Play Store/App Store)
|
|
1527
|
+
|
|
1528
|
+
\uC635\uC158:
|
|
1529
|
+
--platform android|ios \uBC30\uD3EC \uD50C\uB7AB\uD3FC (\uAE30\uBCF8: android)
|
|
1530
|
+
--app <id> \uC571 ID \uC9C0\uC815
|
|
1531
|
+
--version-code <n> \uBE4C\uB4DC \uBC88\uD638 \uC9C1\uC811 \uC9C0\uC815 (--skip-build \uC640 \uD568\uAED8)
|
|
1532
|
+
--from <ref> \uCEE4\uBC0B \uBC94\uC704 \uC2DC\uC791 (\uB9B4\uB9AC\uC988 \uB178\uD2B8\uC6A9)
|
|
1533
|
+
--to <ref> \uCEE4\uBC0B \uBC94\uC704 \uB05D (\uAE30\uBCF8: HEAD)
|
|
1534
|
+
--language <\uCF54\uB4DC> \uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC5B8\uC5B4 (\uAE30\uBCF8: ko-KR)
|
|
1535
|
+
--dry-run \uC2E4\uC81C \uBC30\uD3EC \uC5C6\uC774 \uD30C\uC774\uD504\uB77C\uC778 \uD14C\uC2A4\uD2B8
|
|
1536
|
+
--yes, -y \uBC30\uD3EC \uD655\uC778 \uD504\uB86C\uD504\uD2B8 \uC0DD\uB7B5 (\uC2A4\uD06C\uB9BD\uD2B8/\uC790\uB3D9\uD654\uC6A9)
|
|
1537
|
+
--skip-build CI \uBE4C\uB4DC \uAC74\uB108\uB700 (--version-code \uD544\uC218)
|
|
1538
|
+
--ci jenkins|github|gitlab CI \uAC15\uC81C \uC120\uD0DD (\uAE30\uBCF8: auto)
|
|
1539
|
+
--workflow <file> GitHub workflow \uD30C\uC77C (\uC608: deploy.yml)
|
|
1540
|
+
--ref <branch|tag> GitHub/GitLab \uBE0C\uB79C\uCE58/\uD0DC\uADF8 (\uAE30\uBCF8: main)
|
|
1541
|
+
setup-jenkins / setup-github / setup-gitlab CI \uC124\uC815 \uB300\uD654\uD615 \uB4F1\uB85D`,
|
|
1542
|
+
mcp: `${kleur9.bold("mimi-seed mcp")} \u2014 Claude/Codex MCP \uC5F0\uACB0
|
|
1543
|
+
|
|
1544
|
+
\uC11C\uBE0C\uBA85\uB839:
|
|
1545
|
+
mimi-seed mcp \uD604\uC7AC \uC124\uC815 + \uB4F1\uB85D \uC548\uB0B4
|
|
1546
|
+
mimi-seed mcp claude Claude Code \uB4F1\uB85D \uBA85\uB839 \uCD9C\uB825
|
|
1547
|
+
mimi-seed mcp codex Codex \uB4F1\uB85D \uC548\uB0B4
|
|
1548
|
+
mimi-seed mcp codex --write ~/.codex/config.toml\uC5D0 \uC9C1\uC811 \uAE30\uB85D (\u26A0 \uC2E4\uC81C \uD1A0\uD070 \uD3C9\uBB38 \uC800\uC7A5)`
|
|
1549
|
+
},
|
|
1550
|
+
help: `${kleur9.bold("mimi-seed")} \u2014 Claude Code/Codex\uC5D0\uC11C \uC571 \uCD9C\uC2DC \uC6B4\uC601
|
|
1551
|
+
|
|
1552
|
+
${kleur9.bold("\uBA85\uB839\uC5B4:")}
|
|
1553
|
+
${kleur9.cyan("mimi-seed init")} \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8\uB97C Mimi Seed\uC5D0 \uC5F0\uACB0
|
|
1554
|
+
${kleur9.cyan("mimi-seed setup")} \uAC00\uC9C4 \uACC4\uC815\uC744 \uD55C \uBC88\uC5D0 \uC5F0\uACB0 (\uC548\uB0B4\uD615 \uB9C8\uBC95\uC0AC)
|
|
1555
|
+
${kleur9.cyan("mimi-seed lang")} \uCD9C\uB825 \uC5B8\uC5B4 (ko / en)
|
|
1556
|
+
${kleur9.cyan("mimi-seed status")} \uC5F0\uACB0 \uC0C1\uD0DC + \uB4F1\uB85D \uC571 \uBAA9\uB85D
|
|
1557
|
+
${kleur9.cyan("mimi-seed auth")} \uC790\uACA9\uC99D\uBA85 \uAC1C\uBCC4 \uC778\uC99D (Google / App Store / Play / Jenkins / CI \u2026)
|
|
1558
|
+
${kleur9.cyan("mimi-seed firebase")} Firebase \uC571 \uC0DD\uC131\xB7config \uB2E4\uC6B4\uB85C\uB4DC\xB7GA4 \uB9C1\uD06C
|
|
1559
|
+
${kleur9.cyan("mimi-seed admob")} AdMob \uACC4\uC815\xB7\uC571\xB7\uAD11\uACE0\uB2E8\uC704 \uC870\uD68C \uBC0F \uC0DD\uC131
|
|
1560
|
+
${kleur9.cyan("mimi-seed ga4")} GA4 property\xB7data stream \uC0DD\uC131\xB7\uC870\uD68C
|
|
1561
|
+
${kleur9.cyan("mimi-seed doctor")} \uD658\uACBD \uC9C4\uB2E8 (\uD1A0\uD070\xB7Git\xB7\uD504\uB85C\uC81D\uD2B8\xB7CI \uCCB4\uD06C)
|
|
1562
|
+
${kleur9.cyan("mimi-seed check")} \uCD9C\uC2DC \uC804 Readiness \uC810\uAC80
|
|
1563
|
+
${kleur9.cyan("mimi-seed notes")} \uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC0DD\uC131 (git log \u2192 AI \u2192 \uB9C8\uCF13 \uC801\uC6A9)
|
|
1564
|
+
${kleur9.cyan("mimi-seed review")} \uB9AC\uBDF0 \uB2F5\uBCC0 AI \uCD08\uC548 \uC0DD\uC131 \uBC0F Play Store \uAC8C\uC2DC
|
|
1565
|
+
${kleur9.cyan("mimi-seed deploy")} \uC571 \uC790\uB3D9 \uBC30\uD3EC (CI \u2192 Play Store/App Store)
|
|
1566
|
+
${kleur9.cyan("mimi-seed mcp")} Claude/Codex MCP \uC5F0\uACB0 \uC548\uB0B4 \uBC0F Codex \uC124\uC815 \uC4F0\uAE30
|
|
1567
|
+
${kleur9.cyan("mimi-seed restart")} MCP \uC11C\uBC84 \uD504\uB85C\uC138\uC2A4 \uC7AC\uC2DC\uC791 (\uAE30\uBCF8: mimi-seed)
|
|
1568
|
+
${kleur9.cyan("mimi-seed logout")} \uB85C\uCEEC \uC124\uC815 \uC0AD\uC81C
|
|
1569
|
+
|
|
1570
|
+
${kleur9.dim("\uAC01 \uBA85\uB839 \uC0C1\uC138 \uC635\uC158:")} ${kleur9.cyan("mimi-seed <command> --help")}
|
|
1571
|
+
|
|
1572
|
+
${kleur9.bold("\uD658\uACBD\uBCC0\uC218:")}
|
|
1573
|
+
MIMI_SEED_TOKEN PAT \uD1A0\uD070 (CI/CD \uBB34\uC778\uC99D \uBAA8\uB4DC)
|
|
1574
|
+
MIMI_SEED_WEB_BASE \uC11C\uBC84 \uC8FC\uC18C (\uAE30\uBCF8: https://mimi-seed.pryzm.gg)
|
|
1575
|
+
ANTHROPIC_API_KEY AI \uB178\uD2B8 \uC0DD\uC131 \uD65C\uC131\uD654 (\uC120\uD0DD)
|
|
1576
|
+
MIMI_SEED_LANG \uCD9C\uB825 \uC5B8\uC5B4 \uAC15\uC81C (ko / en) \u2014 settings.json \uBCF4\uB2E4 \uC6B0\uC120
|
|
1577
|
+
MIMI_SEED_GOOGLE_CLIENT_ID / _SECRET
|
|
1578
|
+
\uC9C1\uC811 \uB9CC\uB4E0 Google OAuth \uD074\uB77C\uC774\uC5B8\uD2B8 \uC0AC\uC6A9 (\uBBF8\uC9C0\uC815 \uC2DC \uB85C\uADF8\uC778 \uB54C \uC6F9 \uCF58\uC194\uC5D0\uC11C \uBC1B\uC544\uC634)
|
|
1579
|
+
`
|
|
1580
|
+
},
|
|
1581
|
+
{
|
|
1582
|
+
noProjectSignal: "\u26A0 No package.json / app.json / android / ios found. Continuing anyway.",
|
|
1583
|
+
detecting: "\u{1F50D} Detecting apps...",
|
|
1584
|
+
noAppDetected: "No app detected. You can register one manually on the web.",
|
|
1585
|
+
unnamed: "(unnamed)",
|
|
1586
|
+
ciMode: "CI mode: using MIMI_SEED_TOKEN",
|
|
1587
|
+
syncFailed: (text) => "Registration failed: " + text,
|
|
1588
|
+
manifest: (created) => ` Release notes SSOT: ${created ? "created" : "verified"} docs/releases.json`,
|
|
1589
|
+
doneCi: "\u2713 Done (CI mode)",
|
|
1590
|
+
waitingLogin: "\u{1F510} Waiting for browser sign-in...",
|
|
1591
|
+
connectFailed: (msg) => "Connection failed: " + msg,
|
|
1592
|
+
tokenReceived: "\u2713 Token received",
|
|
1593
|
+
saved: (location) => ` Saved: ${location}`,
|
|
1594
|
+
registering: "\u{1F504} Registering apps...",
|
|
1595
|
+
claudeAgent: " Claude agent config: .claude/mimi-seed.md",
|
|
1596
|
+
codexAgent: " Codex agent config: AGENTS.md",
|
|
1597
|
+
ready: "\u2713 Ready.",
|
|
1598
|
+
askLike: "Try asking this in Claude Code or Codex:",
|
|
1599
|
+
ask1: ' "Is my app ready to ship?"',
|
|
1600
|
+
ask2: ' "Write the release notes"',
|
|
1601
|
+
ask3: ' "Show my registered apps"',
|
|
1602
|
+
dashboard: (url) => `Dashboard: ${url}`,
|
|
1603
|
+
localTitle: "\u2500\u2500 Extra local MCP setup (--local) \u2500\u2500",
|
|
1604
|
+
localIntro: "The remote MCP (PAT, read + diagnostics) is done above. The local MCP runs every store write tool directly via Google OAuth (Node 20+).",
|
|
1605
|
+
localStep1: "1) Sign in with Google (Firebase / AdMob / Play / Ads):",
|
|
1606
|
+
localStep2: "2) Register the local MCP server (separate from the remote 'mimi-seed'):",
|
|
1607
|
+
localCodexHint: ' Codex: add [mcp_servers.mimi-seed-local] command="npx", args=["-y","@yoonion/mimi-seed-mcp"] to ~/.codex/config.toml',
|
|
1608
|
+
localStep3: "3) Connect the remaining accounts (App Store / Play / Jenkins / CI / social \u2026):",
|
|
1609
|
+
localSetupHint: " Press [?] on any item to see how to obtain that token.",
|
|
1610
|
+
notConnected: "No Mimi Seed account connected. Run `mimi-seed init`.",
|
|
1611
|
+
statusTitle: "Mimi Seed connection status",
|
|
1612
|
+
statusToken: (prefix, date) => ` Token: ${prefix}\u2026 (${date})`,
|
|
1613
|
+
statusEndpoint: (endpoint) => ` Endpoint: ${endpoint}`,
|
|
1614
|
+
appList: "\u{1F4CB} Apps:",
|
|
1615
|
+
listFailed: (text) => "Lookup failed: " + text,
|
|
1616
|
+
logoutDone: "\u2713 Local config deleted.",
|
|
1617
|
+
logoutRevoke: "Revoke the token on the web: /workspace/api-tokens",
|
|
1618
|
+
codexWritten: "\u2713 Codex MCP configured",
|
|
1619
|
+
codexWriteWarn: " \u26A0 The real token is stored in plain text in config.toml (check the file permissions).",
|
|
1620
|
+
codexVerify: "Reopen Codex and verify with `/mcp` or `codex mcp list`.",
|
|
1621
|
+
codexTitle: "Codex MCP registration",
|
|
1622
|
+
codexAuto: "Automatic:",
|
|
1623
|
+
codexManual: "Manual example (~/.codex/config.toml) \u2014 contains the real token:",
|
|
1624
|
+
claudeTitle: "Claude Code MCP registration \u2014 run this one line as-is:",
|
|
1625
|
+
claudeWarn: " \u26A0 This command contains the real token (it stays in your shell history). The token is also stored in ~/.mimi-seed/config.json.",
|
|
1626
|
+
usage: {
|
|
1627
|
+
init: `${kleur9.bold("mimi-seed init")} \u2014 connect the current project to Mimi Seed
|
|
1628
|
+
|
|
1629
|
+
Auto-detects apps (Expo/Gradle/Info.plist/pbxproj) \u2192 issues a PAT in the browser (remote MCP) \u2192 registers the apps
|
|
1630
|
+
+ creates/verifies .claude/mimi-seed.md, AGENTS.md, docs/releases.json.
|
|
1631
|
+
|
|
1632
|
+
Options:
|
|
1633
|
+
--local also sign in with Google OAuth and show local MCP (all store write tools) setup`,
|
|
1634
|
+
setup: `${kleur9.bold("mimi-seed setup")} \u2014 connect the accounts you have, in one pass (guided wizard)
|
|
1635
|
+
|
|
1636
|
+
Shows the connection status first, then asks only about what is not connected yet.
|
|
1637
|
+
Press [?] on any item to learn where and how to obtain that token.
|
|
1638
|
+
Already-connected items are skipped, so you can quit halfway and rerun it later.
|
|
1639
|
+
|
|
1640
|
+
Options:
|
|
1641
|
+
--only <ids> only the given credentials (comma-separated: oauth,appstore,jenkins \u2026)
|
|
1642
|
+
--reconnect <ids> set up again even if already connected
|
|
1643
|
+
--platform android,ios force the platforms (default: auto-detected from the project)
|
|
1644
|
+
--yes, -y ask nothing, just print the status table
|
|
1645
|
+
--non-interactive same as above (for CI)
|
|
1646
|
+
--fail-on-missing exit 1 if a required credential is missing (CI gate)
|
|
1647
|
+
|
|
1648
|
+
${kleur9.dim("In non-TTY / CI environments it prints the status table only, with no prompts.")}`,
|
|
1649
|
+
lang: `${kleur9.bold("mimi-seed lang")} \u2014 CLI output language (\uD55C\uAD6D\uC5B4 / English)
|
|
1650
|
+
|
|
1651
|
+
mimi-seed lang show current language
|
|
1652
|
+
mimi-seed lang ko \uD55C\uAD6D\uC5B4 (default)
|
|
1653
|
+
mimi-seed lang en English
|
|
1654
|
+
|
|
1655
|
+
${kleur9.dim("Stored in ~/.mimi-seed/settings.json. MIMI_SEED_LANG takes precedence when set.")}
|
|
1656
|
+
${kleur9.dim("The setup wizard asks on first run, so you rarely need to type this.")}`,
|
|
1657
|
+
status: `${kleur9.bold("mimi-seed status")} \u2014 connection status + registered apps. No options.`,
|
|
1658
|
+
doctor: `${kleur9.bold("mimi-seed doctor")} \u2014 environment check (token \xB7 Node \xB7 Git \xB7 project \xB7 CI). No options.`,
|
|
1659
|
+
logout: `${kleur9.bold("mimi-seed logout")} \u2014 delete the local config (config.json). No options.`,
|
|
1660
|
+
restart: `${kleur9.bold("mimi-seed restart")} \u2014 restart the MCP server process (default: mimi-seed)
|
|
1661
|
+
|
|
1662
|
+
mimi-seed restart [server-name]`,
|
|
1663
|
+
notes: `${kleur9.bold("mimi-seed notes")} \u2014 generate release notes (git log \u2192 AI \u2192 push to stores)
|
|
1664
|
+
|
|
1665
|
+
Options:
|
|
1666
|
+
--from <ref> start commit/tag (default: latest tag)
|
|
1667
|
+
--to <ref> end commit (default: HEAD)
|
|
1668
|
+
--locale ko,en-US target locales (comma-separated)
|
|
1669
|
+
--apply push to the stores right after generating
|
|
1670
|
+
--no-interactive CI mode (no prompts)
|
|
1671
|
+
--limit <n> max commits (default: 30)`,
|
|
1672
|
+
check: `${kleur9.bold("mimi-seed check")} \u2014 pre-release readiness check
|
|
1673
|
+
|
|
1674
|
+
Options:
|
|
1675
|
+
--app <id> app ID
|
|
1676
|
+
--fail-on-blocker exit 1 if a blocker is found (for CI)`,
|
|
1677
|
+
review: `${kleur9.bold("mimi-seed review")} \u2014 draft a review reply with AI and post it to the Play Store
|
|
1678
|
+
|
|
1679
|
+
Options:
|
|
1680
|
+
--text <content> the review text (interactive prompt if omitted)
|
|
1681
|
+
--rating <1-5> star rating
|
|
1682
|
+
--tone <tone> friendly / professional / empathetic / brief (default: friendly)
|
|
1683
|
+
--language <code> reply language (default: ko)
|
|
1684
|
+
--app-name <name> app name (for context)
|
|
1685
|
+
--apply post the reply to the Play Store
|
|
1686
|
+
--review-id <id> review ID (required with --apply)
|
|
1687
|
+
--package-name <p> package name (required with --apply)
|
|
1688
|
+
--no-interactive CI mode`,
|
|
1689
|
+
deploy: `${kleur9.bold("mimi-seed deploy")} \u2014 automated app release (CI build \u2192 Play Store/App Store)
|
|
1690
|
+
|
|
1691
|
+
Options:
|
|
1692
|
+
--platform android|ios target platform (default: android)
|
|
1693
|
+
--app <id> app ID
|
|
1694
|
+
--version-code <n> set the build number explicitly (with --skip-build)
|
|
1695
|
+
--from <ref> commit range start (for release notes)
|
|
1696
|
+
--to <ref> commit range end (default: HEAD)
|
|
1697
|
+
--language <code> release notes language (default: ko-KR)
|
|
1698
|
+
--dry-run exercise the pipeline without releasing
|
|
1699
|
+
--yes, -y skip the release confirmation prompt (scripts/automation)
|
|
1700
|
+
--skip-build skip the CI build (--version-code required)
|
|
1701
|
+
--ci jenkins|github|gitlab force the CI provider (default: auto)
|
|
1702
|
+
--workflow <file> GitHub workflow file (e.g. deploy.yml)
|
|
1703
|
+
--ref <branch|tag> GitHub/GitLab branch/tag (default: main)
|
|
1704
|
+
setup-jenkins / setup-github / setup-gitlab interactive CI setup`,
|
|
1705
|
+
mcp: `${kleur9.bold("mimi-seed mcp")} \u2014 Claude/Codex MCP connection
|
|
1706
|
+
|
|
1707
|
+
Subcommands:
|
|
1708
|
+
mimi-seed mcp current config + setup instructions
|
|
1709
|
+
mimi-seed mcp claude print the Claude Code registration command
|
|
1710
|
+
mimi-seed mcp codex Codex setup instructions
|
|
1711
|
+
mimi-seed mcp codex --write write straight into ~/.codex/config.toml (\u26A0 stores the real token in plain text)`
|
|
1712
|
+
},
|
|
1713
|
+
help: `${kleur9.bold("mimi-seed")} \u2014 app release ops from Claude Code/Codex
|
|
1714
|
+
|
|
1715
|
+
${kleur9.bold("Commands:")}
|
|
1716
|
+
${kleur9.cyan("mimi-seed init")} connect the current project to Mimi Seed
|
|
1717
|
+
${kleur9.cyan("mimi-seed setup")} connect the accounts you have, in one pass (guided wizard)
|
|
1718
|
+
${kleur9.cyan("mimi-seed lang")} output language (ko / en)
|
|
1719
|
+
${kleur9.cyan("mimi-seed status")} connection status + registered apps
|
|
1720
|
+
${kleur9.cyan("mimi-seed auth")} connect credentials one by one (Google / App Store / Play / Jenkins / CI \u2026)
|
|
1721
|
+
${kleur9.cyan("mimi-seed firebase")} create Firebase apps, download configs, link GA4
|
|
1722
|
+
${kleur9.cyan("mimi-seed admob")} list and create AdMob accounts, apps, ad units
|
|
1723
|
+
${kleur9.cyan("mimi-seed ga4")} create and list GA4 properties and data streams
|
|
1724
|
+
${kleur9.cyan("mimi-seed doctor")} environment check (token \xB7 Git \xB7 project \xB7 CI)
|
|
1725
|
+
${kleur9.cyan("mimi-seed check")} pre-release readiness check
|
|
1726
|
+
${kleur9.cyan("mimi-seed notes")} generate release notes (git log \u2192 AI \u2192 push to stores)
|
|
1727
|
+
${kleur9.cyan("mimi-seed review")} draft a review reply with AI and post it to the Play Store
|
|
1728
|
+
${kleur9.cyan("mimi-seed deploy")} automated app release (CI \u2192 Play Store/App Store)
|
|
1729
|
+
${kleur9.cyan("mimi-seed mcp")} Claude/Codex MCP setup instructions and Codex config writing
|
|
1730
|
+
${kleur9.cyan("mimi-seed restart")} restart the MCP server process (default: mimi-seed)
|
|
1731
|
+
${kleur9.cyan("mimi-seed logout")} delete the local config
|
|
1732
|
+
|
|
1733
|
+
${kleur9.dim("Per-command options:")} ${kleur9.cyan("mimi-seed <command> --help")}
|
|
1734
|
+
|
|
1735
|
+
${kleur9.bold("Environment variables:")}
|
|
1736
|
+
MIMI_SEED_TOKEN PAT token (headless CI/CD mode)
|
|
1737
|
+
MIMI_SEED_WEB_BASE server address (default: https://mimi-seed.pryzm.gg)
|
|
1738
|
+
ANTHROPIC_API_KEY enable AI note generation (optional)
|
|
1739
|
+
MIMI_SEED_LANG force the output language (ko / en) \u2014 beats settings.json
|
|
1740
|
+
MIMI_SEED_GOOGLE_CLIENT_ID / _SECRET
|
|
1741
|
+
use your own Google OAuth client (otherwise fetched from the web console at sign-in)
|
|
1742
|
+
`
|
|
1743
|
+
}
|
|
1744
|
+
);
|
|
1066
1745
|
function log4(msg) {
|
|
1067
1746
|
process.stdout.write(msg + "\n");
|
|
1068
1747
|
}
|
|
@@ -1073,37 +1752,37 @@ async function cmdInit(args) {
|
|
|
1073
1752
|
log4(kleur9.dim(cwd));
|
|
1074
1753
|
log4("");
|
|
1075
1754
|
if (!await hasAnyProjectSignal(cwd)) {
|
|
1076
|
-
log4(kleur9.yellow(
|
|
1755
|
+
log4(kleur9.yellow(M8().noProjectSignal));
|
|
1077
1756
|
}
|
|
1078
|
-
log4(
|
|
1757
|
+
log4(M8().detecting);
|
|
1079
1758
|
const hints = await detectHints(cwd);
|
|
1080
1759
|
if (hints.length === 0) {
|
|
1081
|
-
log4(kleur9.yellow(
|
|
1760
|
+
log4(kleur9.yellow(M8().noAppDetected));
|
|
1082
1761
|
} else {
|
|
1083
1762
|
for (const h of hints) {
|
|
1084
1763
|
const tag = [h.packageName && `android:${h.packageName}`, h.bundleId && `ios:${h.bundleId}`].filter(Boolean).join(" ");
|
|
1085
|
-
log4(` \u2022 ${h.name ??
|
|
1764
|
+
log4(` \u2022 ${h.name ?? M8().unnamed} ${kleur9.dim(tag)}`);
|
|
1086
1765
|
}
|
|
1087
1766
|
}
|
|
1088
1767
|
log4("");
|
|
1089
1768
|
if (process.env.MIMI_SEED_TOKEN) {
|
|
1090
1769
|
const cfg2 = await getEffectiveConfig();
|
|
1091
1770
|
if (cfg2 && hints.length > 0) {
|
|
1092
|
-
log4(kleur9.dim(
|
|
1771
|
+
log4(kleur9.dim(M8().ciMode));
|
|
1093
1772
|
const payload = hints.map((h) => ({ name: h.name, packageName: h.packageName, bundleId: h.bundleId }));
|
|
1094
1773
|
const result = await mcpCall(cfg2.endpoint, cfg2.token, "sync_apps", { hints: payload });
|
|
1095
1774
|
if (result.isError) {
|
|
1096
|
-
log4(kleur9.red(
|
|
1775
|
+
log4(kleur9.red(M8().syncFailed(result.text)));
|
|
1097
1776
|
} else {
|
|
1098
1777
|
for (const line of result.text.split("\n")) log4(" " + line);
|
|
1099
1778
|
}
|
|
1100
1779
|
}
|
|
1101
1780
|
const manifest2 = await ensureReleaseManifest(cwd);
|
|
1102
|
-
log4(kleur9.dim(
|
|
1103
|
-
log4(kleur9.bold(
|
|
1781
|
+
log4(kleur9.dim(M8().manifest(manifest2.created)));
|
|
1782
|
+
log4(kleur9.bold(M8().doneCi));
|
|
1104
1783
|
return;
|
|
1105
1784
|
}
|
|
1106
|
-
log4(
|
|
1785
|
+
log4(M8().waitingLogin);
|
|
1107
1786
|
const hostName = os3.hostname().slice(0, 32);
|
|
1108
1787
|
const name = `cli-${hostName}`;
|
|
1109
1788
|
const { port, promise } = await awaitHandshake(5 * 60 * 1e3);
|
|
@@ -1115,10 +1794,10 @@ async function cmdInit(args) {
|
|
|
1115
1794
|
try {
|
|
1116
1795
|
handshake = await promise;
|
|
1117
1796
|
} catch (e) {
|
|
1118
|
-
log4(kleur9.red(
|
|
1797
|
+
log4(kleur9.red(M8().connectFailed(e.message)));
|
|
1119
1798
|
process.exit(1);
|
|
1120
1799
|
}
|
|
1121
|
-
log4(kleur9.green(
|
|
1800
|
+
log4(kleur9.green(M8().tokenReceived));
|
|
1122
1801
|
const cfg = {
|
|
1123
1802
|
token: handshake.token,
|
|
1124
1803
|
prefix: handshake.prefix,
|
|
@@ -1127,14 +1806,14 @@ async function cmdInit(args) {
|
|
|
1127
1806
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1128
1807
|
};
|
|
1129
1808
|
await writeConfig(cfg);
|
|
1130
|
-
log4(kleur9.dim(
|
|
1809
|
+
log4(kleur9.dim(M8().saved(CONFIG_LOCATION)));
|
|
1131
1810
|
log4("");
|
|
1132
1811
|
if (hints.length > 0) {
|
|
1133
|
-
log4(
|
|
1812
|
+
log4(M8().registering);
|
|
1134
1813
|
const payload = hints.map((h) => ({ name: h.name, packageName: h.packageName, bundleId: h.bundleId }));
|
|
1135
1814
|
const result = await mcpCall(cfg.endpoint, cfg.token, "sync_apps", { hints: payload });
|
|
1136
1815
|
if (result.isError) {
|
|
1137
|
-
log4(kleur9.red(
|
|
1816
|
+
log4(kleur9.red(M8().syncFailed(result.text)));
|
|
1138
1817
|
} else {
|
|
1139
1818
|
for (const line of result.text.split("\n")) log4(" " + line);
|
|
1140
1819
|
}
|
|
@@ -1187,88 +1866,88 @@ async function cmdInit(args) {
|
|
|
1187
1866
|
if (!fs5.existsSync(claudeAgentPath)) {
|
|
1188
1867
|
fs5.mkdirSync(claudeDir, { recursive: true });
|
|
1189
1868
|
fs5.writeFileSync(claudeAgentPath, agentMd, { mode: 420 });
|
|
1190
|
-
log4(kleur9.dim(
|
|
1869
|
+
log4(kleur9.dim(M8().claudeAgent));
|
|
1191
1870
|
}
|
|
1192
1871
|
const codexAgentPath = path5.join(cwd, "AGENTS.md");
|
|
1193
1872
|
if (!fs5.existsSync(codexAgentPath)) {
|
|
1194
1873
|
fs5.writeFileSync(codexAgentPath, agentMd, { mode: 420 });
|
|
1195
|
-
log4(kleur9.dim(
|
|
1874
|
+
log4(kleur9.dim(M8().codexAgent));
|
|
1196
1875
|
}
|
|
1197
1876
|
const manifest = await ensureReleaseManifest(cwd);
|
|
1198
|
-
log4(kleur9.dim(
|
|
1199
|
-
log4(kleur9.bold(
|
|
1877
|
+
log4(kleur9.dim(M8().manifest(manifest.created)));
|
|
1878
|
+
log4(kleur9.bold(M8().ready));
|
|
1200
1879
|
log4("");
|
|
1201
|
-
log4(
|
|
1202
|
-
log4(kleur9.cyan(
|
|
1203
|
-
log4(kleur9.cyan(
|
|
1204
|
-
log4(kleur9.cyan(
|
|
1880
|
+
log4(M8().askLike);
|
|
1881
|
+
log4(kleur9.cyan(M8().ask1));
|
|
1882
|
+
log4(kleur9.cyan(M8().ask2));
|
|
1883
|
+
log4(kleur9.cyan(M8().ask3));
|
|
1205
1884
|
log4("");
|
|
1206
|
-
log4(
|
|
1885
|
+
log4(M8().dashboard(kleur9.underline(DEFAULT_WEB_BASE + "/apps")));
|
|
1207
1886
|
log4("");
|
|
1208
1887
|
printMcpSetup(cfg);
|
|
1209
1888
|
if (local) {
|
|
1210
1889
|
log4("");
|
|
1211
|
-
log4(kleur9.bold(
|
|
1212
|
-
log4(kleur9.dim(
|
|
1890
|
+
log4(kleur9.bold(M8().localTitle));
|
|
1891
|
+
log4(kleur9.dim(M8().localIntro));
|
|
1213
1892
|
log4("");
|
|
1214
|
-
log4(
|
|
1893
|
+
log4(M8().localStep1);
|
|
1215
1894
|
await cmdAuth(["login"]);
|
|
1216
1895
|
log4("");
|
|
1217
|
-
log4(
|
|
1896
|
+
log4(M8().localStep2);
|
|
1218
1897
|
log4(kleur9.cyan(" claude mcp add mimi-seed-local -- npx -y @yoonion/mimi-seed-mcp"));
|
|
1219
|
-
log4(kleur9.dim(
|
|
1898
|
+
log4(kleur9.dim(M8().localCodexHint));
|
|
1220
1899
|
log4("");
|
|
1221
|
-
log4(
|
|
1900
|
+
log4(M8().localStep3);
|
|
1222
1901
|
log4(kleur9.cyan(" mimi-seed setup"));
|
|
1223
|
-
log4(kleur9.dim(
|
|
1902
|
+
log4(kleur9.dim(M8().localSetupHint));
|
|
1224
1903
|
}
|
|
1225
1904
|
}
|
|
1226
1905
|
async function cmdStatus() {
|
|
1227
1906
|
const cfg = await getEffectiveConfig();
|
|
1228
1907
|
if (!cfg) {
|
|
1229
|
-
log4(kleur9.yellow(
|
|
1908
|
+
log4(kleur9.yellow(M8().notConnected));
|
|
1230
1909
|
process.exit(1);
|
|
1231
1910
|
}
|
|
1232
|
-
log4(kleur9.bold(
|
|
1233
|
-
log4(
|
|
1234
|
-
log4(
|
|
1911
|
+
log4(kleur9.bold(M8().statusTitle));
|
|
1912
|
+
log4(M8().statusToken(cfg.prefix, cfg.createdAt.slice(0, 10)));
|
|
1913
|
+
log4(M8().statusEndpoint(cfg.endpoint));
|
|
1235
1914
|
log4("");
|
|
1236
|
-
log4(
|
|
1915
|
+
log4(M8().appList);
|
|
1237
1916
|
const r = await mcpCall(cfg.endpoint, cfg.token, "list_apps", {});
|
|
1238
1917
|
if (r.isError) {
|
|
1239
|
-
log4(kleur9.red(
|
|
1918
|
+
log4(kleur9.red(M8().listFailed(r.text)));
|
|
1240
1919
|
process.exit(1);
|
|
1241
1920
|
}
|
|
1242
1921
|
for (const line of r.text.split("\n")) log4(" " + line);
|
|
1243
1922
|
}
|
|
1244
1923
|
async function cmdLogout() {
|
|
1245
1924
|
await deleteConfig();
|
|
1246
|
-
log4(kleur9.green(
|
|
1247
|
-
log4(kleur9.dim(
|
|
1925
|
+
log4(kleur9.green(M8().logoutDone));
|
|
1926
|
+
log4(kleur9.dim(M8().logoutRevoke));
|
|
1248
1927
|
}
|
|
1249
1928
|
async function cmdMcp(args) {
|
|
1250
1929
|
const target = args[0] ?? "help";
|
|
1251
1930
|
const cfg = await getEffectiveConfig();
|
|
1252
1931
|
if (!cfg) {
|
|
1253
|
-
log4(kleur9.yellow(
|
|
1932
|
+
log4(kleur9.yellow(M8().notConnected));
|
|
1254
1933
|
process.exit(1);
|
|
1255
1934
|
}
|
|
1256
1935
|
if (target === "codex") {
|
|
1257
1936
|
if (args.includes("--write")) {
|
|
1258
1937
|
const configPath = await writeCodexMcpConfig(cfg);
|
|
1259
|
-
log4(kleur9.green(
|
|
1938
|
+
log4(kleur9.green(M8().codexWritten));
|
|
1260
1939
|
log4(kleur9.dim(` ${configPath}`));
|
|
1261
|
-
log4(kleur9.dim(
|
|
1940
|
+
log4(kleur9.dim(M8().codexWriteWarn));
|
|
1262
1941
|
log4("");
|
|
1263
|
-
log4(
|
|
1942
|
+
log4(M8().codexVerify);
|
|
1264
1943
|
return;
|
|
1265
1944
|
}
|
|
1266
|
-
log4(kleur9.bold(
|
|
1945
|
+
log4(kleur9.bold(M8().codexTitle));
|
|
1267
1946
|
log4("");
|
|
1268
|
-
log4(
|
|
1947
|
+
log4(M8().codexAuto);
|
|
1269
1948
|
log4(kleur9.cyan(" mimi-seed mcp codex --write"));
|
|
1270
1949
|
log4("");
|
|
1271
|
-
log4(
|
|
1950
|
+
log4(M8().codexManual);
|
|
1272
1951
|
log4(`[mcp_servers.mimi-seed]
|
|
1273
1952
|
url = "${cfg.endpoint}"
|
|
1274
1953
|
enabled = true
|
|
@@ -1276,137 +1955,21 @@ http_headers = { Authorization = "Bearer ${cfg.token}" }`);
|
|
|
1276
1955
|
return;
|
|
1277
1956
|
}
|
|
1278
1957
|
if (target === "claude") {
|
|
1279
|
-
log4(kleur9.bold(
|
|
1958
|
+
log4(kleur9.bold(M8().claudeTitle));
|
|
1280
1959
|
log4(kleur9.cyan(` ${claudeMcpAddCommand(cfg)}`));
|
|
1281
|
-
log4(kleur9.dim(
|
|
1960
|
+
log4(kleur9.dim(M8().claudeWarn));
|
|
1282
1961
|
return;
|
|
1283
1962
|
}
|
|
1284
1963
|
printMcpSetup(cfg);
|
|
1285
1964
|
}
|
|
1286
|
-
var CMD_USAGE = {
|
|
1287
|
-
init: `${kleur9.bold("mimi-seed init")} \u2014 \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8\uB97C Mimi Seed\uC5D0 \uC5F0\uACB0
|
|
1288
|
-
|
|
1289
|
-
\uC571 \uC790\uB3D9 \uAC10\uC9C0(Expo/Gradle/Info.plist/pbxproj) \u2192 \uBE0C\uB77C\uC6B0\uC800 PAT \uBC1C\uAE09(\uC6D0\uACA9 MCP) \u2192 \uC571 \uB4F1\uB85D
|
|
1290
|
-
+ .claude/mimi-seed.md, AGENTS.md, docs/releases.json \uC0DD\uC131/\uD655\uC778.
|
|
1291
|
-
|
|
1292
|
-
\uC635\uC158:
|
|
1293
|
-
--local \uCD94\uAC00\uB85C Google OAuth \uB85C\uADF8\uC778 + \uB85C\uCEEC MCP(\uC2A4\uD1A0\uC5B4 \uC4F0\uAE30 \uB3C4\uAD6C \uC804\uCCB4) \uB4F1\uB85D \uC548\uB0B4`,
|
|
1294
|
-
setup: `${kleur9.bold("mimi-seed setup")} \u2014 \uAC00\uC9C4 \uACC4\uC815\uC744 \uD55C \uBC88\uC5D0 \uC5F0\uACB0 (\uC548\uB0B4\uD615 \uB9C8\uBC95\uC0AC)
|
|
1295
|
-
|
|
1296
|
-
\uC5F0\uACB0 \uC0C1\uD0DC\uB97C \uBA3C\uC800 \uBCF4\uC5EC\uC8FC\uACE0, \uC544\uC9C1 \uC5F0\uACB0\uB418\uC9C0 \uC54A\uC740 \uAC83\uB9CC \uC21C\uC11C\uB300\uB85C \uBB3C\uC5B4\uBCF8\uB2E4.
|
|
1297
|
-
\uAC01 \uD56D\uBAA9\uC5D0\uC11C [?] \uB97C \uB204\uB974\uBA74 "\uADF8 \uD1A0\uD070\uC744 \uC5B4\uB514\uC11C \uC5B4\uB5BB\uAC8C \uBC1C\uAE09\uBC1B\uB294\uC9C0"\uB97C \uC54C\uB824\uC900\uB2E4.
|
|
1298
|
-
\uC774\uBBF8 \uC5F0\uACB0\uB41C \uD56D\uBAA9\uC740 \uAC74\uB108\uB6F0\uBBC0\uB85C, \uC911\uAC04\uC5D0 \uADF8\uB9CC\uB450\uACE0 \uB098\uC911\uC5D0 \uB2E4\uC2DC \uC2E4\uD589\uD574\uB3C4 \uB41C\uB2E4.
|
|
1299
|
-
|
|
1300
|
-
\uC635\uC158:
|
|
1301
|
-
--only <ids> \uC9C0\uC815\uD55C \uC790\uACA9\uC99D\uBA85\uB9CC (\uC27C\uD45C \uAD6C\uBD84: oauth,appstore,jenkins \u2026)
|
|
1302
|
-
--reconnect <ids> \uC774\uBBF8 \uC5F0\uACB0\uB3FC \uC788\uC5B4\uB3C4 \uB2E4\uC2DC \uC124\uC815
|
|
1303
|
-
--platform android,ios \uD50C\uB7AB\uD3FC \uAC15\uC81C \uC9C0\uC815 (\uAE30\uBCF8: \uD504\uB85C\uC81D\uD2B8\uC5D0\uC11C \uC790\uB3D9 \uAC10\uC9C0)
|
|
1304
|
-
--yes, -y \uC544\uBB34\uAC83\uB3C4 \uBB3B\uC9C0 \uC54A\uACE0 \uC0C1\uD0DC\uD45C\uB9CC \uCD9C\uB825
|
|
1305
|
-
--non-interactive \uC704\uC640 \uB3D9\uC77C (CI \uC6A9)
|
|
1306
|
-
--fail-on-missing \uD544\uC218 \uC790\uACA9\uC99D\uBA85\uC774 \uC5C6\uC73C\uBA74 exit 1 (CI \uAC8C\uC774\uD2B8)
|
|
1307
|
-
|
|
1308
|
-
${kleur9.dim("\uBE44TTY / CI \uD658\uACBD\uC5D0\uC11C\uB294 \uD504\uB86C\uD504\uD2B8 \uC5C6\uC774 \uC0C1\uD0DC\uD45C\uB9CC \uCD9C\uB825\uD55C\uB2E4.")}`,
|
|
1309
|
-
lang: `${kleur9.bold("mimi-seed lang")} \u2014 CLI \uCD9C\uB825 \uC5B8\uC5B4 (\uD55C\uAD6D\uC5B4 / English)
|
|
1310
|
-
|
|
1311
|
-
mimi-seed lang \uD604\uC7AC \uC5B8\uC5B4 \uD45C\uC2DC
|
|
1312
|
-
mimi-seed lang ko \uD55C\uAD6D\uC5B4 (\uAE30\uBCF8)
|
|
1313
|
-
mimi-seed lang en English
|
|
1314
|
-
|
|
1315
|
-
${kleur9.dim("~/.mimi-seed/settings.json \uC5D0 \uC800\uC7A5\uB429\uB2C8\uB2E4. \uD658\uACBD\uBCC0\uC218 MIMI_SEED_LANG \uAC00 \uC788\uC73C\uBA74 \uADF8\uAC8C \uC6B0\uC120\uD569\uB2C8\uB2E4.")}
|
|
1316
|
-
${kleur9.dim("setup \uB9C8\uBC95\uC0AC\uAC00 \uCCAB \uC2E4\uD589 \uB54C \uBB3C\uC5B4\uBCF4\uBBC0\uB85C \uBCF4\uD1B5\uC740 \uC9C1\uC811 \uCE60 \uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.")}`,
|
|
1317
|
-
status: `${kleur9.bold("mimi-seed status")} \u2014 \uC5F0\uACB0 \uC0C1\uD0DC + \uB4F1\uB85D \uC571 \uBAA9\uB85D. \uC635\uC158 \uC5C6\uC74C.`,
|
|
1318
|
-
doctor: `${kleur9.bold("mimi-seed doctor")} \u2014 \uD658\uACBD \uC9C4\uB2E8 (\uD1A0\uD070\xB7Node\xB7Git\xB7\uD504\uB85C\uC81D\uD2B8\xB7CI). \uC635\uC158 \uC5C6\uC74C.`,
|
|
1319
|
-
logout: `${kleur9.bold("mimi-seed logout")} \u2014 \uB85C\uCEEC \uC124\uC815(config.json) \uC0AD\uC81C. \uC635\uC158 \uC5C6\uC74C.`,
|
|
1320
|
-
restart: `${kleur9.bold("mimi-seed restart")} \u2014 MCP \uC11C\uBC84 \uD504\uB85C\uC138\uC2A4 \uC7AC\uC2DC\uC791 (\uAE30\uBCF8: mimi-seed)
|
|
1321
|
-
|
|
1322
|
-
mimi-seed restart [server-name]`,
|
|
1323
|
-
notes: `${kleur9.bold("mimi-seed notes")} \u2014 \uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC0DD\uC131 (git log \u2192 AI \u2192 \uB9C8\uCF13 \uC801\uC6A9)
|
|
1324
|
-
|
|
1325
|
-
\uC635\uC158:
|
|
1326
|
-
--from <ref> \uC2DC\uC791 \uCEE4\uBC0B/\uD0DC\uADF8 (\uAE30\uBCF8: \uCD5C\uC2E0 \uD0DC\uADF8)
|
|
1327
|
-
--to <ref> \uB05D \uCEE4\uBC0B (\uAE30\uBCF8: HEAD)
|
|
1328
|
-
--locale ko,en-US \uB300\uC0C1 \uB85C\uCF00\uC77C (\uC27C\uD45C \uAD6C\uBD84)
|
|
1329
|
-
--apply \uC0DD\uC131 \uD6C4 \uC2A4\uD1A0\uC5B4\uC5D0 \uBC14\uB85C \uC801\uC6A9
|
|
1330
|
-
--no-interactive CI \uBAA8\uB4DC (\uD504\uB86C\uD504\uD2B8 \uC5C6\uC74C)
|
|
1331
|
-
--limit <n> \uCD5C\uB300 \uCEE4\uBC0B \uC218 (\uAE30\uBCF8: 30)`,
|
|
1332
|
-
check: `${kleur9.bold("mimi-seed check")} \u2014 \uCD9C\uC2DC \uC804 Readiness \uC810\uAC80
|
|
1333
|
-
|
|
1334
|
-
\uC635\uC158:
|
|
1335
|
-
--app <id> \uC571 ID \uC9C0\uC815
|
|
1336
|
-
--fail-on-blocker \uBE14\uB85C\uCEE4 \uC788\uC73C\uBA74 exit 1 (CI\uC6A9)`,
|
|
1337
|
-
review: `${kleur9.bold("mimi-seed review")} \u2014 \uB9AC\uBDF0 \uB2F5\uBCC0 AI \uCD08\uC548 \uC0DD\uC131 \uBC0F Play Store \uAC8C\uC2DC
|
|
1338
|
-
|
|
1339
|
-
\uC635\uC158:
|
|
1340
|
-
--text <\uB0B4\uC6A9> \uB9AC\uBDF0 \uC6D0\uBB38 (\uBBF8\uC785\uB825 \uC2DC \uB300\uD654\uD615 \uD504\uB86C\uD504\uD2B8)
|
|
1341
|
-
--rating <1-5> \uBCC4\uC810
|
|
1342
|
-
--tone <tone> friendly / professional / empathetic / brief (\uAE30\uBCF8: friendly)
|
|
1343
|
-
--language <\uCF54\uB4DC> \uB2F5\uBCC0 \uC5B8\uC5B4 (\uAE30\uBCF8: ko)
|
|
1344
|
-
--app-name <\uC774\uB984> \uC571 \uC774\uB984 (\uB9E5\uB77D\uC6A9)
|
|
1345
|
-
--apply \uB2F5\uBCC0\uC744 Play Store\uC5D0 \uAC8C\uC2DC
|
|
1346
|
-
--review-id <id> \uB9AC\uBDF0 ID (--apply \uC2DC \uD544\uC694)
|
|
1347
|
-
--package-name <p> \uD328\uD0A4\uC9C0\uBA85 (--apply \uC2DC \uD544\uC694)
|
|
1348
|
-
--no-interactive CI \uBAA8\uB4DC`,
|
|
1349
|
-
deploy: `${kleur9.bold("mimi-seed deploy")} \u2014 \uC571 \uC790\uB3D9 \uBC30\uD3EC (CI \uBE4C\uB4DC \u2192 Play Store/App Store)
|
|
1350
|
-
|
|
1351
|
-
\uC635\uC158:
|
|
1352
|
-
--platform android|ios \uBC30\uD3EC \uD50C\uB7AB\uD3FC (\uAE30\uBCF8: android)
|
|
1353
|
-
--app <id> \uC571 ID \uC9C0\uC815
|
|
1354
|
-
--version-code <n> \uBE4C\uB4DC \uBC88\uD638 \uC9C1\uC811 \uC9C0\uC815 (--skip-build \uC640 \uD568\uAED8)
|
|
1355
|
-
--from <ref> \uCEE4\uBC0B \uBC94\uC704 \uC2DC\uC791 (\uB9B4\uB9AC\uC988 \uB178\uD2B8\uC6A9)
|
|
1356
|
-
--to <ref> \uCEE4\uBC0B \uBC94\uC704 \uB05D (\uAE30\uBCF8: HEAD)
|
|
1357
|
-
--language <\uCF54\uB4DC> \uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC5B8\uC5B4 (\uAE30\uBCF8: ko-KR)
|
|
1358
|
-
--dry-run \uC2E4\uC81C \uBC30\uD3EC \uC5C6\uC774 \uD30C\uC774\uD504\uB77C\uC778 \uD14C\uC2A4\uD2B8
|
|
1359
|
-
--yes, -y \uBC30\uD3EC \uD655\uC778 \uD504\uB86C\uD504\uD2B8 \uC0DD\uB7B5 (\uC2A4\uD06C\uB9BD\uD2B8/\uC790\uB3D9\uD654\uC6A9)
|
|
1360
|
-
--skip-build CI \uBE4C\uB4DC \uAC74\uB108\uB700 (--version-code \uD544\uC218)
|
|
1361
|
-
--ci jenkins|github|gitlab CI \uAC15\uC81C \uC120\uD0DD (\uAE30\uBCF8: auto)
|
|
1362
|
-
--workflow <file> GitHub workflow \uD30C\uC77C (\uC608: deploy.yml)
|
|
1363
|
-
--ref <branch|tag> GitHub/GitLab \uBE0C\uB79C\uCE58/\uD0DC\uADF8 (\uAE30\uBCF8: main)
|
|
1364
|
-
setup-jenkins / setup-github / setup-gitlab CI \uC124\uC815 \uB300\uD654\uD615 \uB4F1\uB85D`,
|
|
1365
|
-
mcp: `${kleur9.bold("mimi-seed mcp")} \u2014 Claude/Codex MCP \uC5F0\uACB0
|
|
1366
|
-
|
|
1367
|
-
\uC11C\uBE0C\uBA85\uB839:
|
|
1368
|
-
mimi-seed mcp \uD604\uC7AC \uC124\uC815 + \uB4F1\uB85D \uC548\uB0B4
|
|
1369
|
-
mimi-seed mcp claude Claude Code \uB4F1\uB85D \uBA85\uB839 \uCD9C\uB825
|
|
1370
|
-
mimi-seed mcp codex Codex \uB4F1\uB85D \uC548\uB0B4
|
|
1371
|
-
mimi-seed mcp codex --write ~/.codex/config.toml\uC5D0 \uC9C1\uC811 \uAE30\uB85D (\u26A0 \uC2E4\uC81C \uD1A0\uD070 \uD3C9\uBB38 \uC800\uC7A5)`
|
|
1372
|
-
};
|
|
1373
1965
|
function printCommandHelp(cmd) {
|
|
1374
|
-
const usage =
|
|
1966
|
+
const usage = M8().usage[cmd];
|
|
1375
1967
|
if (!usage) return false;
|
|
1376
1968
|
log4(usage);
|
|
1377
1969
|
return true;
|
|
1378
1970
|
}
|
|
1379
1971
|
function printHelp() {
|
|
1380
|
-
log4(
|
|
1381
|
-
|
|
1382
|
-
${kleur9.bold("\uBA85\uB839\uC5B4:")}
|
|
1383
|
-
${kleur9.cyan("mimi-seed init")} \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8\uB97C Mimi Seed\uC5D0 \uC5F0\uACB0
|
|
1384
|
-
${kleur9.cyan("mimi-seed setup")} \uAC00\uC9C4 \uACC4\uC815\uC744 \uD55C \uBC88\uC5D0 \uC5F0\uACB0 (\uC548\uB0B4\uD615 \uB9C8\uBC95\uC0AC)
|
|
1385
|
-
${kleur9.cyan("mimi-seed lang")} \uCD9C\uB825 \uC5B8\uC5B4 (ko / en)
|
|
1386
|
-
${kleur9.cyan("mimi-seed status")} \uC5F0\uACB0 \uC0C1\uD0DC + \uB4F1\uB85D \uC571 \uBAA9\uB85D
|
|
1387
|
-
${kleur9.cyan("mimi-seed auth")} \uC790\uACA9\uC99D\uBA85 \uAC1C\uBCC4 \uC778\uC99D (Google / App Store / Play / Jenkins / CI \u2026)
|
|
1388
|
-
${kleur9.cyan("mimi-seed firebase")} Firebase \uC571 \uC0DD\uC131\xB7config \uB2E4\uC6B4\uB85C\uB4DC\xB7GA4 \uB9C1\uD06C
|
|
1389
|
-
${kleur9.cyan("mimi-seed admob")} AdMob \uACC4\uC815\xB7\uC571\xB7\uAD11\uACE0\uB2E8\uC704 \uC870\uD68C \uBC0F \uC0DD\uC131
|
|
1390
|
-
${kleur9.cyan("mimi-seed ga4")} GA4 property\xB7data stream \uC0DD\uC131\xB7\uC870\uD68C
|
|
1391
|
-
${kleur9.cyan("mimi-seed doctor")} \uD658\uACBD \uC9C4\uB2E8 (\uD1A0\uD070\xB7Git\xB7\uD504\uB85C\uC81D\uD2B8\xB7CI \uCCB4\uD06C)
|
|
1392
|
-
${kleur9.cyan("mimi-seed check")} \uCD9C\uC2DC \uC804 Readiness \uC810\uAC80
|
|
1393
|
-
${kleur9.cyan("mimi-seed notes")} \uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC0DD\uC131 (git log \u2192 AI \u2192 \uB9C8\uCF13 \uC801\uC6A9)
|
|
1394
|
-
${kleur9.cyan("mimi-seed review")} \uB9AC\uBDF0 \uB2F5\uBCC0 AI \uCD08\uC548 \uC0DD\uC131 \uBC0F Play Store \uAC8C\uC2DC
|
|
1395
|
-
${kleur9.cyan("mimi-seed deploy")} \uC571 \uC790\uB3D9 \uBC30\uD3EC (CI \u2192 Play Store/App Store)
|
|
1396
|
-
${kleur9.cyan("mimi-seed mcp")} Claude/Codex MCP \uC5F0\uACB0 \uC548\uB0B4 \uBC0F Codex \uC124\uC815 \uC4F0\uAE30
|
|
1397
|
-
${kleur9.cyan("mimi-seed restart")} MCP \uC11C\uBC84 \uD504\uB85C\uC138\uC2A4 \uC7AC\uC2DC\uC791 (\uAE30\uBCF8: mimi-seed)
|
|
1398
|
-
${kleur9.cyan("mimi-seed logout")} \uB85C\uCEEC \uC124\uC815 \uC0AD\uC81C
|
|
1399
|
-
|
|
1400
|
-
${kleur9.dim("\uAC01 \uBA85\uB839 \uC0C1\uC138 \uC635\uC158:")} ${kleur9.cyan("mimi-seed <command> --help")}
|
|
1401
|
-
|
|
1402
|
-
${kleur9.bold("\uD658\uACBD\uBCC0\uC218:")}
|
|
1403
|
-
MIMI_SEED_TOKEN PAT \uD1A0\uD070 (CI/CD \uBB34\uC778\uC99D \uBAA8\uB4DC)
|
|
1404
|
-
MIMI_SEED_WEB_BASE \uC11C\uBC84 \uC8FC\uC18C (\uAE30\uBCF8: https://mimi-seed.pryzm.gg)
|
|
1405
|
-
ANTHROPIC_API_KEY AI \uB178\uD2B8 \uC0DD\uC131 \uD65C\uC131\uD654 (\uC120\uD0DD)
|
|
1406
|
-
MIMI_SEED_LANG \uCD9C\uB825 \uC5B8\uC5B4 \uAC15\uC81C (ko / en) \u2014 settings.json \uBCF4\uB2E4 \uC6B0\uC120
|
|
1407
|
-
MIMI_SEED_GOOGLE_CLIENT_ID / _SECRET
|
|
1408
|
-
\uC9C1\uC811 \uB9CC\uB4E0 Google OAuth \uD074\uB77C\uC774\uC5B8\uD2B8 \uC0AC\uC6A9 (\uBBF8\uC9C0\uC815 \uC2DC \uB85C\uADF8\uC778 \uB54C \uC6F9 \uCF58\uC194\uC5D0\uC11C \uBC1B\uC544\uC634)
|
|
1409
|
-
`);
|
|
1972
|
+
log4(M8().help);
|
|
1410
1973
|
}
|
|
1411
1974
|
async function main() {
|
|
1412
1975
|
const cmd = process.argv[2];
|
|
@@ -1470,12 +2033,12 @@ async function main() {
|
|
|
1470
2033
|
printHelp();
|
|
1471
2034
|
break;
|
|
1472
2035
|
default:
|
|
1473
|
-
log4(kleur9.red(
|
|
2036
|
+
log4(kleur9.red(t().common.unknownCommand(cmd)));
|
|
1474
2037
|
printHelp();
|
|
1475
2038
|
process.exit(1);
|
|
1476
2039
|
}
|
|
1477
2040
|
} catch (e) {
|
|
1478
|
-
log4(kleur9.red(
|
|
2041
|
+
log4(kleur9.red(t().common.error(e.message)));
|
|
1479
2042
|
if (process.env.DEBUG) log4(e.stack ?? "");
|
|
1480
2043
|
process.exit(1);
|
|
1481
2044
|
}
|