noiton 1.0.0 → 2.0.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/README.md +46 -31
- package/package.json +25 -8
- package/src/commands/change.js +44 -54
- package/src/commands/init.js +266 -43
- package/src/commands/refresh.js +59 -47
- package/src/commands/remove.js +46 -22
- package/src/commands/status.js +58 -31
- package/src/constants.js +31 -17
- package/src/index.js +21 -10
- package/src/lib/agents/aider.js +141 -0
- package/src/lib/agents/cline.js +128 -0
- package/src/lib/agents/hermes.js +156 -0
- package/src/lib/agents/index.js +82 -0
- package/src/lib/agents/kilo.js +140 -0
- package/src/lib/agents/kimi.js +149 -0
- package/src/lib/agents/openclaw.js +155 -0
- package/src/lib/agents/opencode.js +177 -0
- package/src/lib/detect.js +286 -0
- package/src/lib/install.js +210 -0
- package/src/messages.js +169 -0
- package/src/octopus.js +272 -0
- package/src/ui.js +196 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NOITON Installer - auto-installation of supported agents
|
|
3
|
+
*
|
|
4
|
+
* Provides install/uninstall/update flows with spinners.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { execSync, spawn } from "node:child_process";
|
|
8
|
+
import { successMessage, errorMessage, installingMessage } from "../messages.js";
|
|
9
|
+
import { spinner, ok, fail, info, dim } from "../ui.js";
|
|
10
|
+
import { c } from "../constants.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Run a shell command and stream output. Returns a promise that resolves
|
|
14
|
+
* with exit code or rejects with the error.
|
|
15
|
+
* @param {string} cmd
|
|
16
|
+
* @param {object} opts
|
|
17
|
+
* @param {(chunk: string) => void} [opts.onData]
|
|
18
|
+
*/
|
|
19
|
+
function execStream(cmd, opts = {}) {
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
const child = spawn(cmd, {
|
|
22
|
+
shell: true,
|
|
23
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
let combined = "";
|
|
27
|
+
child.stdout.on("data", (d) => {
|
|
28
|
+
const s = d.toString();
|
|
29
|
+
combined += s;
|
|
30
|
+
if (opts.onData) opts.onData(s);
|
|
31
|
+
});
|
|
32
|
+
child.stderr.on("data", (d) => {
|
|
33
|
+
const s = d.toString();
|
|
34
|
+
combined += s;
|
|
35
|
+
if (opts.onData) opts.onData(s);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
child.on("error", (err) => reject(err));
|
|
39
|
+
child.on("close", (code) => {
|
|
40
|
+
if (code === 0) resolve(combined);
|
|
41
|
+
else reject(new Error(`Comando falhou com código ${code}`));
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Install an agent by ID.
|
|
48
|
+
* @param {string} agentId
|
|
49
|
+
* @returns {Promise<{ok: boolean, output?: string, error?: string}>}
|
|
50
|
+
*/
|
|
51
|
+
export async function installAgent(agentId) {
|
|
52
|
+
const { AGENT_REGISTRY } = await import("./detect.js");
|
|
53
|
+
const agent = AGENT_REGISTRY.find((a) => a.id === agentId);
|
|
54
|
+
if (!agent || !agent.installCmd) {
|
|
55
|
+
return { ok: false, error: `Agente ${agentId} não pode ser instalado automaticamente` };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const s = spinner(`${installingMessage()} Instalando ${agent.name}...`);
|
|
59
|
+
try {
|
|
60
|
+
const output = await execStream(agent.installCmd, {
|
|
61
|
+
onData: () => s.text = `${installingMessage()} Instalando ${agent.name}...`,
|
|
62
|
+
});
|
|
63
|
+
s.succeed(`${agent.name} instalado!`);
|
|
64
|
+
return { ok: true, output };
|
|
65
|
+
} catch (err) {
|
|
66
|
+
s.fail(`Erro ao instalar ${agent.name}`);
|
|
67
|
+
return { ok: false, error: err.message };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Update an agent to latest version.
|
|
73
|
+
* @param {string} agentId
|
|
74
|
+
* @returns {Promise<{ok: boolean, error?: string}>}
|
|
75
|
+
*/
|
|
76
|
+
export async function updateAgent(agentId) {
|
|
77
|
+
const { AGENT_REGISTRY } = await import("./detect.js");
|
|
78
|
+
const agent = AGENT_REGISTRY.find((a) => a.id === agentId);
|
|
79
|
+
if (!agent) return { ok: false, error: `Agente ${agentId} desconhecido` };
|
|
80
|
+
|
|
81
|
+
const updateCmds = {
|
|
82
|
+
opencode: "curl -fsSL https://opencode.ai/install | bash",
|
|
83
|
+
kilo: "npm update -g @kilocode/cli",
|
|
84
|
+
aider: "pip install --upgrade aider-chat",
|
|
85
|
+
hermes: "pip install --upgrade nous-hermes",
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const cmd = updateCmds[agentId];
|
|
89
|
+
if (!cmd) return { ok: false, error: `Update não suportado para ${agent.name}` };
|
|
90
|
+
|
|
91
|
+
const s = spinner(`Atualizando ${agent.name}...`);
|
|
92
|
+
try {
|
|
93
|
+
await execStream(cmd);
|
|
94
|
+
s.succeed(`${agent.name} atualizado!`);
|
|
95
|
+
return { ok: true };
|
|
96
|
+
} catch (err) {
|
|
97
|
+
s.fail(`Erro ao atualizar ${agent.name}`);
|
|
98
|
+
return { ok: false, error: err.message };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Quick check if command exists (used by checkAgentAvailable).
|
|
104
|
+
* @param {string} cmd
|
|
105
|
+
*/
|
|
106
|
+
function commandExists(cmd) {
|
|
107
|
+
try {
|
|
108
|
+
execSync(`command -v ${cmd}`, { stdio: "ignore" });
|
|
109
|
+
return true;
|
|
110
|
+
} catch {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Check if Python is available (needed for pip installs).
|
|
117
|
+
*/
|
|
118
|
+
export function pythonAvailable() {
|
|
119
|
+
return commandExists("python3") || commandExists("python");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Get current OpenCode version from binary.
|
|
124
|
+
* @returns {string|null}
|
|
125
|
+
*/
|
|
126
|
+
export function getOpenCodeVersion() {
|
|
127
|
+
try {
|
|
128
|
+
const out = execSync("opencode --version 2>/dev/null", {
|
|
129
|
+
encoding: "utf8",
|
|
130
|
+
timeout: 5000,
|
|
131
|
+
});
|
|
132
|
+
const match = out.match(/(\d+\.\d+(?:\.\d+)?)/);
|
|
133
|
+
return match ? match[1] : out.trim();
|
|
134
|
+
} catch {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Confirm dialog using inquirer (re-exported for convenience).
|
|
141
|
+
*/
|
|
142
|
+
import { confirm } from "@inquirer/prompts";
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Offer to install OpenCode when none found.
|
|
146
|
+
* Asks the user a few quick questions to choose between OpenCode and Hermes.
|
|
147
|
+
*/
|
|
148
|
+
export async function offerInstall() {
|
|
149
|
+
const { select } = await import("@inquirer/prompts");
|
|
150
|
+
console.log();
|
|
151
|
+
info(c.bold("🐙 Vamos descobrir o que você precisa!"));
|
|
152
|
+
console.log();
|
|
153
|
+
const useCase = await select({
|
|
154
|
+
message: "Pra que você quer usar IA?",
|
|
155
|
+
choices: [
|
|
156
|
+
{
|
|
157
|
+
name: "💻 Programar (código, debug, refatorar)",
|
|
158
|
+
value: "programming",
|
|
159
|
+
description: "Recomenda: OpenCode",
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: "🤖 Assistente (tarefas, integrações)",
|
|
163
|
+
value: "assistant",
|
|
164
|
+
description: "Recomenda: Hermes",
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: "🤔 Não sei, me explica as diferenças",
|
|
168
|
+
value: "explain",
|
|
169
|
+
description: "Mostra comparação detalhada",
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
if (useCase === "explain") {
|
|
175
|
+
info("🐙 OpenCode: programador IA que escreve código junto com você");
|
|
176
|
+
info("🐙 Hermes: assistente que faz tarefas e se integra com apps");
|
|
177
|
+
console.log();
|
|
178
|
+
return offerInstall();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const wantInstall = await confirm({
|
|
182
|
+
message: `${useCase === "programming" ? "💻 OpenCode" : "🤖 Hermes"} é o que brilha aí. Instalar agora?`,
|
|
183
|
+
default: true,
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
if (!wantInstall) return null;
|
|
187
|
+
|
|
188
|
+
return useCase === "programming" ? "opencode" : "hermes";
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Compare current and latest version, return update message if needed.
|
|
193
|
+
* @param {string} currentVer
|
|
194
|
+
* @param {string} latestVer
|
|
195
|
+
* @returns {string|null}
|
|
196
|
+
*/
|
|
197
|
+
export function needsUpdateMessage(currentVer, latestVer) {
|
|
198
|
+
if (!currentVer || !latestVer) return null;
|
|
199
|
+
const cur = currentVer.split(".").map(Number);
|
|
200
|
+
const lat = latestVer.split(".").map(Number);
|
|
201
|
+
for (let i = 0; i < Math.max(cur.length, lat.length); i++) {
|
|
202
|
+
const c = cur[i] || 0;
|
|
203
|
+
const l = lat[i] || 0;
|
|
204
|
+
if (l > c) {
|
|
205
|
+
return `🔄 OpenCode v${latestVer} disponível! Você tem v${currentVer}.`;
|
|
206
|
+
}
|
|
207
|
+
if (l < c) return null;
|
|
208
|
+
}
|
|
209
|
+
return null;
|
|
210
|
+
}
|
package/src/messages.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NOITON Chatty - funny phrases, easter eggs, and contextual messages
|
|
3
|
+
*
|
|
4
|
+
* Each "moment" returns a random phrase from its pool. Some pools are
|
|
5
|
+
* time-bound (easter eggs for holidays), others are rare (5% chance).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { c } from "./constants.js";
|
|
9
|
+
|
|
10
|
+
const TODAY = () => {
|
|
11
|
+
const d = new Date();
|
|
12
|
+
return { month: d.getMonth() + 1, day: d.getDate(), weekday: d.getDay() };
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// ============= PHRASE POOLS =============
|
|
16
|
+
|
|
17
|
+
const successStart = [
|
|
18
|
+
"Houston, temos um coder! 🚀 Bora decolar!",
|
|
19
|
+
"✨ Pronto! Agora você fala a língua dos modelos!",
|
|
20
|
+
"🎉 Tá preparado, astronauta do código! Tudo conectado!",
|
|
21
|
+
"🧠 Sua IA tá conectada. Que o código esteja com você!",
|
|
22
|
+
"💜 Bem-vindo ao clube dos que quebram galho!",
|
|
23
|
+
"🤖 beep boop... chave aceita. Iniciando protocolo de poder.",
|
|
24
|
+
"⚡ Acabou de ganhar superpoderes. Use com responsabilidade!",
|
|
25
|
+
"🌟 Pronto pra criar o que ninguém pensou em criar!",
|
|
26
|
+
"🎯 Agora você é 10x developer. (Métricas não inclusas)",
|
|
27
|
+
"🍕 Sua pizza tá no forno... quer dizer, seu código!",
|
|
28
|
+
"🐙 O polvo abraçou você. Que os commits sejam verdes!",
|
|
29
|
+
"🔮 Os ventos do digital lhe favorecem. Mystic vibes on.",
|
|
30
|
+
"🎪 Espetáculo vai começar - você é a estrela!",
|
|
31
|
+
"💎 Brilhante! Como diamante em superfície de código.",
|
|
32
|
+
"🦄 Você está oficialmente powered by a magic sea creature.",
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const noAgentPhrases = [
|
|
36
|
+
"🌵 Aqui só tem deserto digital...",
|
|
37
|
+
"👻 Achou que ia rodar sozinho? Pior que precisa de um agent!",
|
|
38
|
+
"🦗 *grilo* ... bora instalar o OpenCode?",
|
|
39
|
+
"🐙 O polvo está olhando pra você esperando uma direção...",
|
|
40
|
+
"🕳️ Tão vazio quanto geladeira de estagiário em sexta-feira.",
|
|
41
|
+
"🌌 Silêncio cósmico... nenhum agente responde.",
|
|
42
|
+
"🤷 Sua máquina tá mais vazia que estacionamento de shopping domingo.",
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const installingPhrases = [
|
|
46
|
+
"📥 Instalando mais rápido que wifi de lan house!",
|
|
47
|
+
"🔧 Apertando parafusos digitais...",
|
|
48
|
+
"⚙️ Calibrando tentáculos do polvo...",
|
|
49
|
+
"🚀 Decolando em 3... 2... 1...",
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
const thinkingPhrases = [
|
|
53
|
+
"🤔 Pensando mais rápido que polvo em aquário...",
|
|
54
|
+
"💭 Sondando as profundezas do digital...",
|
|
55
|
+
"🐙 O polvo está consultando seus 8 cérebros...",
|
|
56
|
+
"⚡ Calculando a matrix...",
|
|
57
|
+
"✨ Alinhando os chakras da configuração...",
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
const errorPhrases = [
|
|
61
|
+
"💥 Ih, o polvo tropeçou no próprio tentáculo!",
|
|
62
|
+
"🤕 Até polvo erra às vezes, né?",
|
|
63
|
+
"🥴 Houston, temos um problema (mas é pequeno, confia).",
|
|
64
|
+
"🦑 Enroscaram os fios. Tenta de novo?",
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
const cancelPhrases = [
|
|
68
|
+
"✋ Operação cancelada. O polvo acenou tchau.",
|
|
69
|
+
"🐙 Tudo bem, o polvo vai pescar!",
|
|
70
|
+
"👋 Sem stress. Volta quando quiser!",
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
const farewell = [
|
|
74
|
+
"🐙 O polvo manda um abraço de 8 tentáculos!",
|
|
75
|
+
"✨ Até a próxima conexão!",
|
|
76
|
+
"🚀 Vai lá brilhar, astronauta!",
|
|
77
|
+
"💜 Tchau! O polvo cuida de você.",
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
const rarePhrases = [
|
|
81
|
+
"🦄 Você encontrou o unicórnio! Bug-free garantido* (*exceto às terças)",
|
|
82
|
+
"👽 Aliens detectados no código. A IA neutralizou.",
|
|
83
|
+
"🍕 Pizza virtual entregue! Calorias: 0",
|
|
84
|
+
"🎰 Você é o visitante nº 1.337! Ganhou superpoderes extras.",
|
|
85
|
+
"🏆 NOITON Pro Tip #42: Polvos são mais espertos que devs (segredo)",
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
const easterEggs = [
|
|
89
|
+
// Seasonal
|
|
90
|
+
{ date: { month: 12, day: 25 }, message: "🎄 HO HO HO! Papai Noel trouxe superpoderes de IA!", emoji: "🎄" },
|
|
91
|
+
{ date: { month: 12, day: 31 }, message: "🎆 Feliz Ano Novo! Que seus bugs sejam poucos!", emoji: "🎆" },
|
|
92
|
+
{ date: { month: 1, day: 1 }, message: "🥂 Feliz 2026! Que venha o código limpo!", emoji: "🥂" },
|
|
93
|
+
{ date: { month: 9, day: 13 }, message: "👨💻 Feliz Dia do Programador! Café grátis (simbólico)!", emoji: "👨💻" },
|
|
94
|
+
{ date: { month: 10, day: 31 }, message: "🎃 BOO! Fantasmas no código? A IA resolve!", emoji: "🎃" },
|
|
95
|
+
{ date: { month: 2, day: 14 }, message: "💘 Você <3 NOITON. O polvo sabe.", emoji: "💘" },
|
|
96
|
+
{ date: { month: 6, day: 12 }, message: "🇧🇷 Viva o Brasil! O polvo tá sambando!", emoji: "🇧🇷" },
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
// ============= EASTER EGG FUNCTION =============
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Check for holiday/spacial date easter egg.
|
|
103
|
+
* Returns a message string or null.
|
|
104
|
+
*/
|
|
105
|
+
export function getEasterEgg() {
|
|
106
|
+
const { month, day } = TODAY();
|
|
107
|
+
const egg = easterEggs.find((e) => e.date.month === month && e.date.day === day);
|
|
108
|
+
if (egg) return egg.message;
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Get a random phrase from a pool
|
|
114
|
+
* Optionally include holiday easter egg in the pool
|
|
115
|
+
*/
|
|
116
|
+
function pick(pool, count = 1) {
|
|
117
|
+
const egg = getEasterEgg();
|
|
118
|
+
const combined = egg ? [egg, ...pool] : pool;
|
|
119
|
+
const shuffled = [...combined].sort(() => Math.random() - 0.5);
|
|
120
|
+
return shuffled.slice(0, count);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ============= PUBLIC MESSAGE FUNCTIONS =============
|
|
124
|
+
|
|
125
|
+
export function successMessage() {
|
|
126
|
+
const pick1 = pick(successStart, 1)[0];
|
|
127
|
+
const pick2 = pick(rarePhrases, 1)[0];
|
|
128
|
+
// 5% chance of rare phrase
|
|
129
|
+
const showRare = Math.random() < 0.05;
|
|
130
|
+
return showRare ? `${pick1}\n\n${c.dim("💎 Easter egg:")} ${pick2}` : pick1;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function farewellMessage() {
|
|
134
|
+
return pick(farewell, 1)[0];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function noAgentMessage() {
|
|
138
|
+
return pick(noAgentPhrases, 1)[0];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function installingMessage() {
|
|
142
|
+
return pick(installingPhrases, 1)[0];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function thinkingMessage() {
|
|
146
|
+
return pick(thinkingPhrases, 1)[0];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function errorMessage() {
|
|
150
|
+
return pick(errorPhrases, 1)[0];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function cancelMessage() {
|
|
154
|
+
return pick(cancelPhrases, 1)[0];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// All goodbye variants - randomly rotate
|
|
158
|
+
export function randomGoodbye() {
|
|
159
|
+
const options = [
|
|
160
|
+
"🐙 O polvo mandou um abraço!",
|
|
161
|
+
"✨ Que os commits sejam verdes!",
|
|
162
|
+
"🚀 Vai lá brilhar!",
|
|
163
|
+
"💜 Tchauzinho do NOITON!",
|
|
164
|
+
"🎯 Acerta em cheio!",
|
|
165
|
+
"🐙 *squish* (tradução: até mais)",
|
|
166
|
+
"👋 Bye bye do polvo!",
|
|
167
|
+
];
|
|
168
|
+
return options[Math.floor(Math.random() * options.length)];
|
|
169
|
+
}
|
package/src/octopus.js
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NOITON Octopus Mascot - "O Polvo NOITON"
|
|
3
|
+
* A beautiful refined octopus that appears throughout the CLI.
|
|
4
|
+
*
|
|
5
|
+
* Design philosophy:
|
|
6
|
+
* - Soft, organic curves (not blocky)
|
|
7
|
+
* - Visible 8 tentacles spread gracefully
|
|
8
|
+
* - Friendly expressive eyes
|
|
9
|
+
* - Brand gradient: purple → magenta → cyan
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import gradient from "gradient-string";
|
|
13
|
+
|
|
14
|
+
// NOITON brand gradient (purple → magenta → cyan → teal)
|
|
15
|
+
const brandGradient = gradient([
|
|
16
|
+
"#A78BFA", // light purple
|
|
17
|
+
"#C084FC", // purple
|
|
18
|
+
"#E879F9", // magenta
|
|
19
|
+
"#F472B6", // pink
|
|
20
|
+
"#22D3EE", // cyan
|
|
21
|
+
"#2DD4BF", // teal
|
|
22
|
+
]);
|
|
23
|
+
|
|
24
|
+
const successGradient = gradient(["#10B981", "#34D399", "#22D3EE", "#A78BFA"]);
|
|
25
|
+
const errorGradient = gradient(["#F87171", "#EF4444", "#DC2626"]);
|
|
26
|
+
const warningGradient = gradient(["#FBBF24", "#F59E0B", "#FB923C"]);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The main NOITON Octopus - smiling, tentacles spread, ready to help
|
|
30
|
+
* Refined organic design with graceful curves
|
|
31
|
+
*/
|
|
32
|
+
export function octopusHappy() {
|
|
33
|
+
return brandGradient.multiline(`
|
|
34
|
+
▄▄▄▄▄
|
|
35
|
+
▄█▀▀▀▀▀▀▀█▄
|
|
36
|
+
▄█▀ ▄▄▄▄▄ ▀█▄
|
|
37
|
+
██ █ o o █ ██
|
|
38
|
+
██ █ ▼ █ ██
|
|
39
|
+
██ ▀▀▀▀▀▀▀ ██
|
|
40
|
+
██ ╲___╱ ██
|
|
41
|
+
██ ▄▄▄▄▄▄▄▄▄ ██
|
|
42
|
+
██ ██████████ ██
|
|
43
|
+
██ ▀▀▀▀▀▀▀▀▀ ██
|
|
44
|
+
▄█▄ ▀▀▀▀▀▀▀▀▀▀ ▄█▄
|
|
45
|
+
▄██████▄ ▄██████▄
|
|
46
|
+
███▀▀▀▀▀▀██▄ ▄██▀▀▀▀▀▀███
|
|
47
|
+
██▀ ▄▄ ▀██▄ ▄██▀ ▄▄ ▀██
|
|
48
|
+
██ ████ ▀██████▀ ████ ██
|
|
49
|
+
█ ██████ ▀███▀ ██████ █
|
|
50
|
+
█ ███████ █ ███████ █
|
|
51
|
+
█ ▀▀▀▀▀▀ █ █ █ ▀▀▀▀▀▀ █
|
|
52
|
+
█ █ █ █ █ █
|
|
53
|
+
█ █ █ █
|
|
54
|
+
▀ █ ♥ █ ▀
|
|
55
|
+
█ █
|
|
56
|
+
`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Compact octopus for inline use (small status)
|
|
61
|
+
*/
|
|
62
|
+
export function octopusMini() {
|
|
63
|
+
return brandGradient.multiline(`
|
|
64
|
+
▄▄▄
|
|
65
|
+
▄█▀▀▀█▄
|
|
66
|
+
██ o o ██
|
|
67
|
+
██ ▼ ██
|
|
68
|
+
▀▀▀▀▀▀
|
|
69
|
+
▄██████▄
|
|
70
|
+
▄█▀ ╲╱ ▀█▄
|
|
71
|
+
█▌ ███ ▐█
|
|
72
|
+
▀▄ ███ ▄▀
|
|
73
|
+
▀▀▀▀▀▀▀
|
|
74
|
+
`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Curious octopus (no agents detected - looking around)
|
|
79
|
+
*/
|
|
80
|
+
export function octopusCurious() {
|
|
81
|
+
return brandGradient.multiline(`
|
|
82
|
+
▄▄▄▄▄
|
|
83
|
+
▄█▀▀▀▀▀▀▀█▄
|
|
84
|
+
▄█▀ ▄▄▄▄▄ ▀█▄
|
|
85
|
+
██ █ ? ? █ ██
|
|
86
|
+
██ █ ▼ █ ██
|
|
87
|
+
██ ▀▀▀▀▀▀▀ ██
|
|
88
|
+
██ ╲___╱ ██
|
|
89
|
+
██ ▄▄▄▄▄▄▄▄▄ ██
|
|
90
|
+
██ ██████████ ██
|
|
91
|
+
██ ▀▀▀▀▀▀▀▀▀ ██
|
|
92
|
+
▀▀▀▀▀▀▀▀▀▀
|
|
93
|
+
▟██████████▙
|
|
94
|
+
▟██████████████▙
|
|
95
|
+
██████████████████
|
|
96
|
+
██████████████
|
|
97
|
+
▀██████████▀
|
|
98
|
+
▀▀▀▀
|
|
99
|
+
`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Working octopus (during long operations - tentacles busy)
|
|
104
|
+
*/
|
|
105
|
+
export function octopusWorking() {
|
|
106
|
+
return brandGradient.multiline(`
|
|
107
|
+
▄▄▄▄▄
|
|
108
|
+
▄█▀▀▀▀▀▀▀█▄
|
|
109
|
+
▄█▀ ▄▄▄▄▄ ▀█▄
|
|
110
|
+
██ █ ~ ~ █ ██
|
|
111
|
+
██ █ ▼ █ ██
|
|
112
|
+
██ ▀▀▀▀▀▀▀ ██
|
|
113
|
+
██ ╲___╱ ██
|
|
114
|
+
██ ▄▄▄▄▄▄▄▄▄ ██
|
|
115
|
+
██ ██████████ ██
|
|
116
|
+
██ ▀▀▀▀▀▀▀▀▀ ██
|
|
117
|
+
▄▄▄▄ ▄▄ ▀▀▀▀▀▀▀▀▀▀ ▄▄ ▄▄▄▄
|
|
118
|
+
█▀▀▀█▄█▀ ▼ ▀█▄█▀▀▀█
|
|
119
|
+
█ ▐██ ▄█████▄ ██▌ █
|
|
120
|
+
█ ██ █████████ ██ █
|
|
121
|
+
█ █▌ █████████ ▐█ █
|
|
122
|
+
█ ▐█ ▀████████▀ █▌ █
|
|
123
|
+
█ ██ ▀▀▀▀▀▀ ██ █
|
|
124
|
+
█ ██▌ ▐██ █
|
|
125
|
+
▐▄██ ██▄▌
|
|
126
|
+
▀▀ ▀▀
|
|
127
|
+
`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Happy dancing octopus (success state - celebrating)
|
|
132
|
+
*/
|
|
133
|
+
export function octopusDancing() {
|
|
134
|
+
return successGradient.multiline(`
|
|
135
|
+
▄▄▄▄▄
|
|
136
|
+
▄█▀▀▀▀▀▀▀█▄
|
|
137
|
+
▄█▀ ▄▄▄▄▄ ▀█▄
|
|
138
|
+
██ █ ^ ^ █ ██
|
|
139
|
+
██ █ ◡ █ ██
|
|
140
|
+
██ ▀▀▀▀▀▀▀ ██
|
|
141
|
+
██ ╲___╱ ██
|
|
142
|
+
██ ▄▄▄▄▄▄▄▄▄ ██
|
|
143
|
+
██ ██████████ ██
|
|
144
|
+
██ ▀▀▀▀▀▀▀▀▀ ██
|
|
145
|
+
✦ ▄▄ ▀▀▀▀▀▀▀▀▀▀ ▄▄ ✦
|
|
146
|
+
★ ▄██▌ ▐██▄ ★
|
|
147
|
+
▄████▌ ╲ ╱ ▐████▄
|
|
148
|
+
██████ ╲ ╱ ██████
|
|
149
|
+
██████ ╲ ╱ ██████
|
|
150
|
+
▀████ ╲╱ ████▀
|
|
151
|
+
▀▀▌ ★ ╲╱ ╲╱ ★ ▐▀▀
|
|
152
|
+
█ ╲╱ █
|
|
153
|
+
▀ ▀
|
|
154
|
+
♥ ♪ ♥ ♪ ♥
|
|
155
|
+
`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Sad octopus (on errors - drooping tentacles)
|
|
160
|
+
*/
|
|
161
|
+
export function octopusSad() {
|
|
162
|
+
return errorGradient.multiline(`
|
|
163
|
+
▄▄▄▄▄
|
|
164
|
+
▄█▀▀▀▀▀▀▀█▄
|
|
165
|
+
▄█▀ ▄▄▄▄▄ ▀█▄
|
|
166
|
+
██ █ . . █ ██
|
|
167
|
+
██ █ ▽ █ ██
|
|
168
|
+
██ ▀▀▀▀▀▀▀ ██
|
|
169
|
+
██ ╲___╱ ██
|
|
170
|
+
██ ▄▄▄▄▄▄▄▄▄ ██
|
|
171
|
+
██ ██████████ ██
|
|
172
|
+
██ ▀▀▀▀▀▀▀▀▀ ██
|
|
173
|
+
▀▀▀▀▀▀▀▀▀▀
|
|
174
|
+
▟▙ ▟▙
|
|
175
|
+
▟███▙ ▟███▙
|
|
176
|
+
██████▙ ▟█████
|
|
177
|
+
██████▙ ▟██████
|
|
178
|
+
▀█████▙ ▟█████▀
|
|
179
|
+
▀▀▀██▙▟██▀▀▀
|
|
180
|
+
▀▀▀
|
|
181
|
+
`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Sleeping octopus (idle/loading)
|
|
186
|
+
*/
|
|
187
|
+
export function octopusSleeping() {
|
|
188
|
+
return brandGradient.multiline(`
|
|
189
|
+
▄▄▄▄▄
|
|
190
|
+
▄█▀▀▀▀▀▀▀█▄
|
|
191
|
+
▄█▀ ▄▄▄▄▄ ▀█▄
|
|
192
|
+
██ █ - - █ ██
|
|
193
|
+
██ █ ▬ █ ██
|
|
194
|
+
██ ▀▀▀▀▀▀▀ ██
|
|
195
|
+
██ ╲___╱ ██
|
|
196
|
+
██ ▄▄▄▄▄▄▄▄▄ ██
|
|
197
|
+
██ ██████████ ██
|
|
198
|
+
██ ▀▀▀▀▀▀▀▀▀ ██
|
|
199
|
+
▀▀▀▀▀▀▀▀▀▀▄
|
|
200
|
+
▟██████████▙█▄
|
|
201
|
+
▟██████████████▙
|
|
202
|
+
██████████████████
|
|
203
|
+
██████████████
|
|
204
|
+
▀██████████▀ z
|
|
205
|
+
▀▀▀▀ zZ
|
|
206
|
+
zZZ
|
|
207
|
+
`);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Octopus typing code (during configuration)
|
|
212
|
+
*/
|
|
213
|
+
export function octopusCoding() {
|
|
214
|
+
return brandGradient.multiline(`
|
|
215
|
+
▄▄▄▄▄
|
|
216
|
+
▄█▀▀▀▀▀▀▀█▄
|
|
217
|
+
▄█▀ ▄▄▄▄▄ ▀█▄
|
|
218
|
+
██ █ @ @ █ ██
|
|
219
|
+
██ █ ▼ █ ██
|
|
220
|
+
██ ▀▀▀▀▀▀▀ ██
|
|
221
|
+
██ ╲___╱ ██
|
|
222
|
+
██ ▄▄▄▄▄▄▄▄▄ ██
|
|
223
|
+
██ ██████████ ██
|
|
224
|
+
██ ▀▀▀▀▀▀▀▀▀ ██
|
|
225
|
+
▟█▙ ▄▄ ▀▀▀▀▀▀▀▀▀▀ ▄▄ ▟█▙
|
|
226
|
+
▟███▙ ▐██▙ ▟██▌ ▟███▙
|
|
227
|
+
█▀▀▀█▄ ▐███▙ ▟███▌ ▄█▀▀▀█
|
|
228
|
+
█ █ ████▙ ▟████ █ █
|
|
229
|
+
█ █ █████▙ ▟█████ █ █
|
|
230
|
+
█ ▐█ ██████▙▟███████ █▌ █
|
|
231
|
+
█ █▌ ██████████████ ▐█ █
|
|
232
|
+
▐█ ▀████████████▀ █▌
|
|
233
|
+
█ ▀▀▀▀▀▀▀▀▀ █
|
|
234
|
+
█ < / > < / > █
|
|
235
|
+
▀ ▟█████████████▙ ▀
|
|
236
|
+
`);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* NOITON logo with octopus
|
|
241
|
+
*/
|
|
242
|
+
export function octopusLogo() {
|
|
243
|
+
return brandGradient.multiline(`
|
|
244
|
+
▟███████▙ ███╗ ██╗ ██████╗ ██╗████████╗ ██████╗ ███╗ ██╗
|
|
245
|
+
▟███████████▙ ████╗ ██║██╔═══██╗██║╚══██╔══╝██╔═══██╗████╗ ██║
|
|
246
|
+
███████████████████╔██╗██║██║ ██║██║ ██║ ██║ ██║██╔██╗ ██║
|
|
247
|
+
████░░░░░░░░░░░░░░██╔██║██║██║ ██║██║ ██║ ██║ ██║██║╚██╗██║
|
|
248
|
+
████▓▓░░░░░░░░░░░░╚═███╔╝╚██████╔╝██║ ██║ ╚██████╔╝██║ ╚████║
|
|
249
|
+
██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ╚══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
|
|
250
|
+
██▓▓▓▓▓▓██▓▓▓▓▓▓██ Universal AI Agent Connector
|
|
251
|
+
████▓▓██▓▓▓▓████ ═══════════════════════
|
|
252
|
+
██▓▓██▓▓██▓▓██
|
|
253
|
+
████████████
|
|
254
|
+
██ ██ ██
|
|
255
|
+
`);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Get a random octopus pose
|
|
260
|
+
*/
|
|
261
|
+
export function randomOctopus() {
|
|
262
|
+
const poses = [octopusHappy, octopusDancing, octopusCoding, octopusSleeping];
|
|
263
|
+
const pick = poses[Math.floor(Math.random() * poses.length)];
|
|
264
|
+
return pick();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export {
|
|
268
|
+
brandGradient,
|
|
269
|
+
successGradient,
|
|
270
|
+
errorGradient,
|
|
271
|
+
warningGradient,
|
|
272
|
+
};
|