markov-cli 1.0.12 → 1.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/auth.js +23 -0
- package/src/commands/setup.js +13 -0
- package/src/interactive.js +91 -12
- package/src/ollama.js +8 -3
- package/src/tools.js +3 -1
- package/src/ui/logo.js +36 -9
package/package.json
CHANGED
package/src/auth.js
CHANGED
|
@@ -6,6 +6,7 @@ const CONFIG_DIR = join(homedir(), '.markov');
|
|
|
6
6
|
const TOKEN_PATH = join(CONFIG_DIR, 'token');
|
|
7
7
|
const ANTHROPIC_KEY_PATH = join(CONFIG_DIR, 'anthropic_api_key');
|
|
8
8
|
const OPENAI_KEY_PATH = join(CONFIG_DIR, 'openai_api_key');
|
|
9
|
+
const OLLAMA_KEY_PATH = join(CONFIG_DIR, 'ollama_api_key');
|
|
9
10
|
|
|
10
11
|
export const API_URL = 'https://api.livingcloud.app/api';
|
|
11
12
|
|
|
@@ -31,6 +32,28 @@ export function clearOpenAIKey() {
|
|
|
31
32
|
delete process.env.OPENAI_API_KEY;
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
export function getOllamaKey() {
|
|
36
|
+
const env = process.env.OLLAMA_API_KEY?.trim();
|
|
37
|
+
if (env) return env;
|
|
38
|
+
if (!existsSync(OLLAMA_KEY_PATH)) return null;
|
|
39
|
+
return readFileSync(OLLAMA_KEY_PATH, 'utf-8').trim() || null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function setOllamaKey(key) {
|
|
43
|
+
const trimmed = (key && String(key).trim()) || '';
|
|
44
|
+
if (!trimmed) return;
|
|
45
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
46
|
+
writeFileSync(OLLAMA_KEY_PATH, trimmed, 'utf-8');
|
|
47
|
+
process.env.OLLAMA_API_KEY = trimmed;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function clearOllamaKey() {
|
|
51
|
+
if (existsSync(OLLAMA_KEY_PATH)) {
|
|
52
|
+
writeFileSync(OLLAMA_KEY_PATH, '', 'utf-8');
|
|
53
|
+
}
|
|
54
|
+
delete process.env.OLLAMA_API_KEY;
|
|
55
|
+
}
|
|
56
|
+
|
|
34
57
|
export function getClaudeKey() {
|
|
35
58
|
const env = process.env.ANTHROPIC_API_KEY?.trim();
|
|
36
59
|
if (env) return env;
|
package/src/commands/setup.js
CHANGED
|
@@ -68,5 +68,18 @@ export const TANSTACK_STEPS = [
|
|
|
68
68
|
|
|
69
69
|
/** Laravel setup steps. */
|
|
70
70
|
export const LARAVEL_STEPS = [
|
|
71
|
+
{ type: 'run', cmd: 'mkdir laravel-be' },
|
|
72
|
+
{ type: 'cd', path: 'laravel-be' },
|
|
71
73
|
{ type: 'run', cmd: 'composer create-project laravel/laravel .' },
|
|
74
|
+
{ type: 'run', cmd: 'npm install && npm run build' },
|
|
72
75
|
];
|
|
76
|
+
|
|
77
|
+
/** Prompt for /laravel: steps as run_terminal_command + file edits only. */
|
|
78
|
+
export const LARAVEL_BLOG_PROMPT = `Set up a new Laravel project "laravel-be" with the following steps:
|
|
79
|
+
|
|
80
|
+
1. run_terminal_command: composer --version
|
|
81
|
+
2. run_terminal_command: php --version
|
|
82
|
+
3. run_terminal_command: composer create-project laravel/laravel laravel-be
|
|
83
|
+
4. run_terminal_command: cd laravel-be
|
|
84
|
+
|
|
85
|
+
If a step fails, stop and report the error.`;
|
package/src/interactive.js
CHANGED
|
@@ -7,10 +7,10 @@ import { resolve } from 'path';
|
|
|
7
7
|
import { printLogo } from './ui/logo.js';
|
|
8
8
|
import { chatWithTools, streamChat, streamChatWithTools, MODEL, MODEL_OPTIONS, setModelAndProvider, getModelDisplayName } from './ollama.js';
|
|
9
9
|
import { resolveFileRefs } from './files.js';
|
|
10
|
-
import { RUN_TERMINAL_COMMAND_TOOL, WEB_SEARCH_TOOL, runTool } from './tools.js';
|
|
10
|
+
import { RUN_TERMINAL_COMMAND_TOOL, WEB_SEARCH_TOOL, runTool, execCommand } from './tools.js';
|
|
11
11
|
import { chatPrompt } from './input.js';
|
|
12
12
|
import { getFilesAndDirs } from './ui/picker.js';
|
|
13
|
-
import { getToken, login, clearToken, getClaudeKey, setClaudeKey, getOpenAIKey, setOpenAIKey } from './auth.js';
|
|
13
|
+
import { getToken, login, clearToken, getClaudeKey, setClaudeKey, getOpenAIKey, setOpenAIKey, getOllamaKey, setOllamaKey } from './auth.js';
|
|
14
14
|
|
|
15
15
|
// Extracted UI modules
|
|
16
16
|
import { selectFrom, confirm, promptLine, promptSecret } from './ui/prompts.js';
|
|
@@ -25,7 +25,7 @@ import { runAgentLoop, maybePrintFullPayload, AGENT_LOOP_MAX_ITERATIONS } from '
|
|
|
25
25
|
import { applyCodeBlockEdits } from './editor/codeBlockEdits.js';
|
|
26
26
|
|
|
27
27
|
// Extracted command modules
|
|
28
|
-
import { runSetupSteps, NEXTJS_STEPS, TANSTACK_STEPS, LARAVEL_STEPS } from './commands/setup.js';
|
|
28
|
+
import { runSetupSteps, NEXTJS_STEPS, TANSTACK_STEPS, LARAVEL_STEPS, LARAVEL_BLOG_PROMPT } from './commands/setup.js';
|
|
29
29
|
|
|
30
30
|
const agentGradient = gradient(['#22c55e', '#16a34a', '#4ade80']);
|
|
31
31
|
|
|
@@ -48,7 +48,7 @@ const INTRO_TEXT =
|
|
|
48
48
|
chalk.cyan(' /init') + chalk.dim(' [prompt] create markov.md with project summary\n') +
|
|
49
49
|
chalk.cyan(' /plan') + chalk.dim(' [prompt] stream a plan and save to plan.md\n') +
|
|
50
50
|
chalk.cyan(' /build') + chalk.dim(' execute plan from plan.md\n') +
|
|
51
|
-
chalk.cyan(' /yolo') + chalk.dim(' [prompt]
|
|
51
|
+
chalk.cyan(' /yolo') + chalk.dim(' [prompt] plan in stream mode, then auto-run until done\n') +
|
|
52
52
|
chalk.dim('\nType a message · ') + chalk.cyan('@filename') + chalk.dim(' to attach · ctrl+q to cancel\n');
|
|
53
53
|
|
|
54
54
|
const HELP_TEXT =
|
|
@@ -59,9 +59,10 @@ const HELP_TEXT =
|
|
|
59
59
|
chalk.cyan(' /setup-nextjs') + chalk.dim(' scaffold a Next.js app\n') +
|
|
60
60
|
chalk.cyan(' /setup-tanstack') + chalk.dim(' scaffold a TanStack Start app\n') +
|
|
61
61
|
chalk.cyan(' /setup-laravel') + chalk.dim(' scaffold a Laravel API\n') +
|
|
62
|
+
chalk.cyan(' /laravel') + chalk.dim(' set up Laravel "my-blog" with blog route (agent)\n') +
|
|
62
63
|
chalk.cyan(' /models') + chalk.dim(' switch the active AI model\n') +
|
|
63
64
|
chalk.cyan(' /cd [path]') + chalk.dim(' change working directory\n') +
|
|
64
|
-
chalk.cyan(' /cmd [command]') + chalk.dim('
|
|
65
|
+
chalk.cyan(' /cmd [command]') + chalk.dim(' run a shell command in the current folder\n') +
|
|
65
66
|
chalk.cyan(' /login') + chalk.dim(' authenticate with email & password\n') +
|
|
66
67
|
chalk.cyan(' /logout') + chalk.dim(' clear saved auth token\n') +
|
|
67
68
|
chalk.cyan(' /clear') + chalk.dim(' clear chat history and stored plan\n') +
|
|
@@ -70,7 +71,7 @@ const HELP_TEXT =
|
|
|
70
71
|
chalk.cyan(' /init') + chalk.dim(' [prompt] create markov.md with project summary\n') +
|
|
71
72
|
chalk.cyan(' /plan') + chalk.dim(' [prompt] stream a plan and save to plan.md\n') +
|
|
72
73
|
chalk.cyan(' /build') + chalk.dim(' execute plan from plan.md\n') +
|
|
73
|
-
chalk.cyan(' /yolo') + chalk.dim(' [prompt]
|
|
74
|
+
chalk.cyan(' /yolo') + chalk.dim(' [prompt] plan in stream mode, then auto-run until done\n') +
|
|
74
75
|
chalk.dim('\nType a message · ') + chalk.cyan('@filename') + chalk.dim(' to attach · ctrl+q to cancel\n');
|
|
75
76
|
|
|
76
77
|
/** If MARKOV_DEBUG is set, print the raw model output after completion. */
|
|
@@ -196,6 +197,7 @@ export async function startInteractive() {
|
|
|
196
197
|
console.log(chalk.yellow('No prompt given.\n'));
|
|
197
198
|
continue;
|
|
198
199
|
}
|
|
200
|
+
console.log(chalk.dim('You: ') + rawUserContent);
|
|
199
201
|
const userContent = (await getLsContext()) + (await getGrepContext()) + 'Create a step-by-step plan for: ' + rawUserContent;
|
|
200
202
|
chatMessages.push({ role: 'user', content: userContent });
|
|
201
203
|
const planMessages = [buildPlanSystemMessage(), ...chatMessages];
|
|
@@ -265,7 +267,7 @@ export async function startInteractive() {
|
|
|
265
267
|
continue;
|
|
266
268
|
}
|
|
267
269
|
}
|
|
268
|
-
console.log(chalk.cyan(' ▶ ') + chalk.bold(name) + chalk.dim(' ') + (name === 'web_search' ? (args?.query ?? '') : (args?.command ?? '')));
|
|
270
|
+
console.log(chalk.cyan('\n ▶ ') + chalk.bold(name) + chalk.dim(' ') + (name === 'web_search' ? (args?.query ?? '') : (args?.command ?? '')));
|
|
269
271
|
const result = await runTool(name, args ?? {}, { cwd: process.cwd(), confirmFn: () => Promise.resolve(true) });
|
|
270
272
|
currentPlanMessages.push({
|
|
271
273
|
role: 'tool',
|
|
@@ -302,6 +304,7 @@ export async function startInteractive() {
|
|
|
302
304
|
console.log(chalk.yellow('No prompt given.\n'));
|
|
303
305
|
continue;
|
|
304
306
|
}
|
|
307
|
+
console.log(chalk.dim('You: ') + rawUserContent);
|
|
305
308
|
const planUserContent = (await getLsContext()) + (await getGrepContext()) + 'Create a step-by-step plan for: ' + rawUserContent;
|
|
306
309
|
chatMessages.push({ role: 'user', content: planUserContent });
|
|
307
310
|
const planMessages = [buildPlanSystemMessage(), ...chatMessages];
|
|
@@ -348,7 +351,7 @@ export async function startInteractive() {
|
|
|
348
351
|
continue;
|
|
349
352
|
}
|
|
350
353
|
}
|
|
351
|
-
console.log(chalk.cyan(' ▶ ') + chalk.bold(name) + chalk.dim(' ') + (name === 'web_search' ? (args?.query ?? '') : (args?.command ?? '')));
|
|
354
|
+
console.log(chalk.cyan('\n ▶ ') + chalk.bold(name) + chalk.dim(' ') + (name === 'web_search' ? (args?.query ?? '') : (args?.command ?? '')));
|
|
352
355
|
const result = await runTool(name, args ?? {}, { cwd: process.cwd(), confirmFn: () => Promise.resolve(true) });
|
|
353
356
|
currentPlanMessages.push({
|
|
354
357
|
role: 'tool',
|
|
@@ -407,7 +410,7 @@ export async function startInteractive() {
|
|
|
407
410
|
},
|
|
408
411
|
onToolCall: (name, args) => {
|
|
409
412
|
const summary = formatToolCallSummary(name, args);
|
|
410
|
-
console.log(chalk.cyan(' ▶ ') + chalk.bold(name) + chalk.dim(' ') + chalk.white(summary));
|
|
413
|
+
console.log(chalk.cyan('\n ▶ ') + chalk.bold(name) + chalk.dim(' ') + chalk.white(summary));
|
|
411
414
|
},
|
|
412
415
|
onToolResult: (name, resultStr) => {
|
|
413
416
|
console.log(chalk.dim(' ') + formatToolResultSummary(name, resultStr));
|
|
@@ -503,7 +506,7 @@ export async function startInteractive() {
|
|
|
503
506
|
continue;
|
|
504
507
|
}
|
|
505
508
|
}
|
|
506
|
-
console.log(chalk.cyan(' ▶ ') + chalk.bold(name) + chalk.dim(' ') + (name === 'web_search' ? (args?.query ?? '') : (args?.command ?? '')));
|
|
509
|
+
console.log(chalk.cyan('\n ▶ ') + chalk.bold(name) + chalk.dim(' ') + (name === 'web_search' ? (args?.query ?? '') : (args?.command ?? '')));
|
|
507
510
|
const result = await runTool(name, args ?? {}, { cwd: process.cwd(), confirmFn: () => Promise.resolve(true) });
|
|
508
511
|
currentInitMessages.push({
|
|
509
512
|
role: 'tool',
|
|
@@ -587,7 +590,7 @@ export async function startInteractive() {
|
|
|
587
590
|
},
|
|
588
591
|
onToolCall: (name, args) => {
|
|
589
592
|
const summary = formatToolCallSummary(name, args);
|
|
590
|
-
console.log(chalk.cyan(' ▶ ') + chalk.bold(name) + chalk.dim(' ') + chalk.white(summary));
|
|
593
|
+
console.log(chalk.cyan('\n ▶ ') + chalk.bold(name) + chalk.dim(' ') + chalk.white(summary));
|
|
591
594
|
},
|
|
592
595
|
onToolResult: (name, resultStr) => {
|
|
593
596
|
console.log(chalk.dim(' ') + formatToolResultSummary(name, resultStr));
|
|
@@ -634,6 +637,14 @@ export async function startInteractive() {
|
|
|
634
637
|
}
|
|
635
638
|
setOpenAIKey(enteredKey);
|
|
636
639
|
}
|
|
640
|
+
if (opt.provider === 'ollama' && opt.model.endsWith('-cloud') && !getOllamaKey()) {
|
|
641
|
+
const enteredKey = (await promptSecret('Ollama API key for cloud models (paste then Enter): ')).trim();
|
|
642
|
+
if (!enteredKey) {
|
|
643
|
+
console.log(chalk.yellow('\nNo key entered. Model not switched.\n'));
|
|
644
|
+
continue;
|
|
645
|
+
}
|
|
646
|
+
setOllamaKey(enteredKey);
|
|
647
|
+
}
|
|
637
648
|
setModelAndProvider(opt.provider, opt.model);
|
|
638
649
|
console.log(chalk.dim(`\n🤖 switched to ${chalk.cyan(getModelDisplayName())}\n`));
|
|
639
650
|
}
|
|
@@ -706,6 +717,73 @@ export async function startInteractive() {
|
|
|
706
717
|
continue;
|
|
707
718
|
}
|
|
708
719
|
|
|
720
|
+
// /laravel — run agent with Laravel "my-blog" blog setup prompt (auto-confirm like /yolo)
|
|
721
|
+
if (trimmed === '/laravel') {
|
|
722
|
+
const userContent = (await getLsContext()) + (await getGrepContext()) + LARAVEL_BLOG_PROMPT;
|
|
723
|
+
chatMessages.push({ role: 'user', content: userContent });
|
|
724
|
+
const agentMessages = [buildAgentSystemMessage(), ...chatMessages];
|
|
725
|
+
maybePrintFullPayload(agentMessages);
|
|
726
|
+
const abortController = new AbortController();
|
|
727
|
+
const confirmFn = () => Promise.resolve(true);
|
|
728
|
+
const confirmFileEdit = async () => true;
|
|
729
|
+
const startTime = Date.now();
|
|
730
|
+
const DOTS = ['.', '..', '...'];
|
|
731
|
+
let dotIdx = 0;
|
|
732
|
+
let spinner = null;
|
|
733
|
+
const startSpinner = () => {
|
|
734
|
+
if (spinner) { clearInterval(spinner); spinner = null; }
|
|
735
|
+
dotIdx = 0;
|
|
736
|
+
process.stdout.write(chalk.dim('\nLaravel › '));
|
|
737
|
+
spinner = setInterval(() => {
|
|
738
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
739
|
+
process.stdout.write('\r' + chalk.dim('Laravel › ') + chalk.dim(elapsed + 's ') + agentGradient(DOTS[dotIdx % DOTS.length]) + ' ');
|
|
740
|
+
dotIdx++;
|
|
741
|
+
}, 400);
|
|
742
|
+
};
|
|
743
|
+
const stopSpinner = () => {
|
|
744
|
+
if (spinner) { clearInterval(spinner); spinner = null; }
|
|
745
|
+
process.stdout.write('\r\x1b[0J');
|
|
746
|
+
};
|
|
747
|
+
try {
|
|
748
|
+
const result = await runAgentLoop(agentMessages, {
|
|
749
|
+
signal: abortController.signal,
|
|
750
|
+
cwd: process.cwd(),
|
|
751
|
+
confirmFn,
|
|
752
|
+
confirmFileEdit,
|
|
753
|
+
onThinking: () => { startSpinner(); },
|
|
754
|
+
onBeforeToolRun: () => { stopSpinner(); },
|
|
755
|
+
onIteration: (iter, max, toolCount) => {
|
|
756
|
+
const w = process.stdout.columns || 80;
|
|
757
|
+
const label = ` Step ${iter} `;
|
|
758
|
+
const line = chalk.dim('──') + chalk.bold.white(label) + chalk.dim('─'.repeat(Math.max(0, w - label.length - 2)));
|
|
759
|
+
console.log(line);
|
|
760
|
+
},
|
|
761
|
+
onToolCall: (name, args) => {
|
|
762
|
+
const summary = formatToolCallSummary(name, args);
|
|
763
|
+
console.log(chalk.cyan('\n ▶ ') + chalk.bold(name) + chalk.dim(' ') + chalk.white(summary));
|
|
764
|
+
},
|
|
765
|
+
onToolResult: (name, resultStr) => {
|
|
766
|
+
console.log(chalk.dim(' ') + formatToolResultSummary(name, resultStr));
|
|
767
|
+
},
|
|
768
|
+
});
|
|
769
|
+
stopSpinner();
|
|
770
|
+
if (result) {
|
|
771
|
+
chatMessages.push(result.finalMessage);
|
|
772
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
773
|
+
const width = Math.min(process.stdout.columns || 80, 80);
|
|
774
|
+
process.stdout.write(formatResponseWithCodeBlocks(result.content, width) + '\n\n');
|
|
775
|
+
await applyCodeBlockEdits(result.content, []);
|
|
776
|
+
allFiles = getFilesAndDirs();
|
|
777
|
+
console.log(chalk.green('✓ Laravel blog setup done.') + chalk.dim(` (${elapsed}s)\n`));
|
|
778
|
+
maybePrintRawModelOutput(result.content);
|
|
779
|
+
}
|
|
780
|
+
} catch (err) {
|
|
781
|
+
stopSpinner();
|
|
782
|
+
if (!abortController.signal?.aborted) console.log(chalk.red(`\n${err.message}\n`));
|
|
783
|
+
}
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
|
|
709
787
|
// Handle message with agent (tools)
|
|
710
788
|
const { loaded, failed, content: resolvedContent } = await resolveFileRefs(trimmed);
|
|
711
789
|
if (loaded.length > 0) {
|
|
@@ -715,6 +793,7 @@ export async function startInteractive() {
|
|
|
715
793
|
console.log(chalk.yellow(`\n⚠ not found: ${failed.map(f => `@${f}`).join(', ')}`));
|
|
716
794
|
}
|
|
717
795
|
const rawUserContent = resolvedContent ?? trimmed;
|
|
796
|
+
console.log(chalk.dim('You: ') + rawUserContent);
|
|
718
797
|
const userContent = (await getLsContext()) + (await getGrepContext()) + rawUserContent;
|
|
719
798
|
chatMessages.push({ role: 'user', content: userContent });
|
|
720
799
|
|
|
@@ -768,7 +847,7 @@ export async function startInteractive() {
|
|
|
768
847
|
},
|
|
769
848
|
onToolCall: (name, args) => {
|
|
770
849
|
const summary = formatToolCallSummary(name, args);
|
|
771
|
-
console.log(chalk.cyan(' ▶ ') + chalk.bold(name) + chalk.dim(' ') + chalk.white(summary));
|
|
850
|
+
console.log(chalk.cyan('\n ▶ ') + chalk.bold(name) + chalk.dim(' ') + chalk.white(summary));
|
|
772
851
|
},
|
|
773
852
|
onToolResult: (name, resultStr) => {
|
|
774
853
|
console.log(chalk.dim(' ') + formatToolResultSummary(name, resultStr));
|
package/src/ollama.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { API_URL, getToken, getClaudeKey, getOpenAIKey } from './auth.js';
|
|
1
|
+
import { API_URL, getToken, getClaudeKey, getOpenAIKey, getOllamaKey } from './auth.js';
|
|
2
2
|
import * as openai from './openai.js';
|
|
3
3
|
import * as claude from './claude.js';
|
|
4
4
|
|
|
@@ -33,7 +33,12 @@ function stripToolCallArtifacts(s) {
|
|
|
33
33
|
|
|
34
34
|
const getHeaders = () => {
|
|
35
35
|
const token = getToken();
|
|
36
|
-
|
|
36
|
+
const ollamaKey = getOllamaKey();
|
|
37
|
+
return {
|
|
38
|
+
'Content-Type': 'application/json',
|
|
39
|
+
...(token && { Authorization: `Bearer ${token}` }),
|
|
40
|
+
...(ollamaKey && { 'X-Ollama-Api-Key': ollamaKey })
|
|
41
|
+
};
|
|
37
42
|
};
|
|
38
43
|
|
|
39
44
|
/** Claude models: { label, model } */
|
|
@@ -51,7 +56,7 @@ export const OPENAI_MODELS = [
|
|
|
51
56
|
];
|
|
52
57
|
|
|
53
58
|
/** Ollama models (backend) */
|
|
54
|
-
export const MODELS = ['qwen3.5:0.8b', 'qwen3.5:2b', 'qwen3.5:4b', 'qwen3.5:9b'];
|
|
59
|
+
export const MODELS = ['qwen3.5:0.8b', 'qwen3.5:2b', 'qwen3.5:4b', 'qwen3.5:9b', 'qwen3.5:397b-cloud'];
|
|
55
60
|
|
|
56
61
|
/** Combined options for /models picker: { label, provider, model } */
|
|
57
62
|
export const MODEL_OPTIONS = [
|
package/src/tools.js
CHANGED
|
@@ -412,7 +412,9 @@ const TOOLS_MAP = {
|
|
|
412
412
|
* @returns {Promise<{ stdout: string, stderr: string, exitCode: number }>}
|
|
413
413
|
*/
|
|
414
414
|
export async function execCommand(command, cwd = process.cwd()) {
|
|
415
|
-
if (
|
|
415
|
+
if (command == null || typeof command !== 'string' || !command.trim()) {
|
|
416
|
+
return { stdout: '', stderr: 'Error: empty or invalid command', exitCode: 1 };
|
|
417
|
+
}
|
|
416
418
|
const timeout = 30_000;
|
|
417
419
|
const maxBuffer = 1024 * 1024;
|
|
418
420
|
try {
|
package/src/ui/logo.js
CHANGED
|
@@ -1,10 +1,28 @@
|
|
|
1
1
|
import gradient from 'gradient-string';
|
|
2
2
|
|
|
3
3
|
const ASCII_ART = `
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
███╗ ███╗ █████╗ ██████╗ ██╗ ██╗ ██████╗ ██╗ ██╗
|
|
5
|
+
████╗ ████║██╔══██╗██╔══██╗██║ ██╔╝██╔═══██╗██║ ██║
|
|
6
|
+
██╔████╔██║███████║██████╔╝█████╔╝ ██║ ██║██║ ██║
|
|
7
|
+
██║╚██╔╝██║██╔══██║██╔══██╗██╔═██╗ ██║ ██║╚██╗ ██╔╝
|
|
8
|
+
██║ ╚═╝ ██║██║ ██║██║ ██║██║ ██╗╚██████╔╝ ╚████╔╝
|
|
9
|
+
╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═══╝
|
|
10
|
+
|
|
11
|
+
██████╗ ██████╗ ██████╗ ███████╗
|
|
12
|
+
██╔════╝██╔═══██╗██╔══██╗██╔════╝
|
|
13
|
+
██║ ██║ ██║██║ ██║█████╗
|
|
14
|
+
██║ ██║ ██║██║ ██║██╔══╝
|
|
15
|
+
╚██████╗╚██████╔╝██████╔╝███████╗
|
|
16
|
+
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
const ASCII_ART4 = `
|
|
20
|
+
██████╗██╗ ███╗ ███╗ █████╗ ██████╗ ██╗ ██╗ ██████╗ ██╗ ██╗
|
|
21
|
+
██╔════╝██║ ████╗ ████║██╔══██╗██╔══██╗██║ ██╔╝██╔═══██╗██║ ██║
|
|
22
|
+
██║ ██║ ██╔████╔██║███████║██████╔╝█████╔╝ ██║ ██║██║ ██║
|
|
23
|
+
██║ ██║ ██║╚██╔╝██║██╔══██║██╔══██╗██╔═██╗ ██║ ██║╚██╗ ██╔╝
|
|
24
|
+
╚██████╗███████╗██║ ╚═╝ ██║██║ ██║██║ ██║██║ ██╗╚██████╔╝ ╚████╔╝
|
|
25
|
+
╚═════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═══╝
|
|
8
26
|
`;
|
|
9
27
|
|
|
10
28
|
const ASCII_ART3 = `
|
|
@@ -14,17 +32,26 @@ const ASCII_ART3 = `
|
|
|
14
32
|
██║╚██╔╝██║██╔══██║██╔══██╗██╔═██╗ ██║ ██║╚██╗ ██╔╝
|
|
15
33
|
██║ ╚═╝ ██║██║ ██║██║ ██║██║ ██╗╚██████╔╝ ╚████╔╝
|
|
16
34
|
╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═══╝
|
|
35
|
+
|
|
36
|
+
██████╗ ██████╗ ██████╗ ███████╗
|
|
37
|
+
██╔════╝██╔═══██╗██╔══██╗██╔════╝
|
|
38
|
+
██║ ██║ ██║██║ ██║█████╗
|
|
39
|
+
██║ ██║ ██║██║ ██║██╔══╝
|
|
40
|
+
╚██████╗╚██████╔╝██████╔╝███████╗
|
|
41
|
+
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
|
|
17
42
|
`;
|
|
18
43
|
|
|
19
44
|
const ASCII_ART2 = `
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
45
|
+
e88'Y88 888 e e 888
|
|
46
|
+
d888 'Y 888 d8b d8b ,"Y88b 888,8, 888 ee e88 88e Y8b Y888P
|
|
47
|
+
C8888 888 e Y8b Y8b "8" 888 888 " 888 P d888 888b Y8b Y8P
|
|
48
|
+
Y888 ,d 888 ,d d8b Y8b Y8b ,ee 888 888 888 b Y888 888P Y8b "
|
|
49
|
+
"88,d88 888,d88 d888b Y8b Y8b "88 888 888 888 8b "88 88" Y8P
|
|
23
50
|
`;
|
|
24
51
|
|
|
25
52
|
|
|
26
|
-
const markovGradient = gradient(['#
|
|
53
|
+
const markovGradient = gradient(['#4ade80', '#6ee7b7', '#38bdf8']);
|
|
27
54
|
|
|
28
55
|
export function printLogo() {
|
|
29
|
-
console.log(markovGradient.multiline(
|
|
56
|
+
console.log(markovGradient.multiline(ASCII_ART4));
|
|
30
57
|
}
|