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
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
# NOITON
|
|
1
|
+
# 🐙 NOITON
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Universal AI Agent Connector** — one key, many agents.
|
|
4
|
+
|
|
5
|
+
NOITON is a CLI wizard that connects your API key to multiple AI coding agents at once. Run it once, pick your agents, paste your key — done.
|
|
4
6
|
|
|
5
7
|
## Quick Start
|
|
6
8
|
|
|
@@ -8,51 +10,64 @@ OpenCode authenticator - configure providers with a single key.
|
|
|
8
10
|
npx noiton
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
The
|
|
12
|
-
1.
|
|
13
|
-
2.
|
|
14
|
-
3.
|
|
15
|
-
4.
|
|
13
|
+
The octopus will:
|
|
14
|
+
1. 🔍 Detect which AI agents are installed (OpenCode, Hermes, OpenClaw, Cline, Aider, Kilo Code, Kimi Code)
|
|
15
|
+
2. 📦 If none found, offer to install OpenCode or Hermes based on your use case
|
|
16
|
+
3. 🔄 If OpenCode is outdated, offer to update it
|
|
17
|
+
4. 🔑 Ask for your NOITON API key (one key serves all agents)
|
|
18
|
+
5. 📋 Fetch available models from the API
|
|
19
|
+
6. ⚙️ Configure each selected agent in its native format
|
|
20
|
+
7. 🎉 Show a funny success message (with easter eggs on holidays!)
|
|
21
|
+
|
|
22
|
+
## Supported Agents
|
|
23
|
+
|
|
24
|
+
| Agent | Type | Config Format | Multiple Models |
|
|
25
|
+
|-------|------|---------------|-----------------|
|
|
26
|
+
| **OpenCode** | CLI | JSON (`opencode.json`) | ✅ |
|
|
27
|
+
| **Hermes** | CLI | YAML (`config.yaml` + `.env`) | Single default |
|
|
28
|
+
| **OpenClaw** | CLI | JSON5 (`openclaw.json`) | ✅ |
|
|
29
|
+
| **Cline** | VS Code ext | JSON (VS Code settings) | Single |
|
|
30
|
+
| **Aider** | CLI | YAML (`.aider.conf.yml` + `.env`) | Single |
|
|
31
|
+
| **Kilo Code** | CLI + VS Code | JSONC (`kilo.jsonc`) | ✅ |
|
|
32
|
+
| **Kimi Code** | CLI + VS Code | TOML (`config.toml`) | Single |
|
|
16
33
|
|
|
17
34
|
## Commands
|
|
18
35
|
|
|
19
36
|
```bash
|
|
20
37
|
npx noiton # Setup wizard (default)
|
|
21
|
-
npx noiton status # Show
|
|
38
|
+
npx noiton status # Show configuration across all agents
|
|
22
39
|
npx noiton refresh # Re-fetch models from API
|
|
23
|
-
npx noiton change # Change API key
|
|
24
|
-
npx noiton remove # Remove NOITON from
|
|
40
|
+
npx noiton change # Change API key in all agents
|
|
41
|
+
npx noiton remove # Remove NOITON from all agents
|
|
25
42
|
npx noiton help # Show help
|
|
43
|
+
npx noiton --version # Show version
|
|
26
44
|
```
|
|
27
45
|
|
|
28
46
|
## How It Works
|
|
29
47
|
|
|
30
|
-
NOITON
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
```
|
|
48
|
+
NOITON detects your installed agents and writes to each one's native config format:
|
|
49
|
+
|
|
50
|
+
- **OpenCode** → `~/.config/opencode/opencode.json` (provider block)
|
|
51
|
+
- **Hermes** → `~/.hermes/config.yaml` (model block) + `~/.hermes/.env` (API key)
|
|
52
|
+
- **OpenClaw** → `~/.openclaw/openclaw.json` (models.providers block)
|
|
53
|
+
- **Cline** → VS Code `settings.json` (cline.* keys)
|
|
54
|
+
- **Aider** → `~/.aider.conf.yml` (openai-api-base) + `~/.env` (OPENAI_API_KEY)
|
|
55
|
+
- **Kilo Code** → `~/.config/kilo/kilo.jsonc` (provider.openai-compatible block)
|
|
56
|
+
- **Kimi Code** → `~/.kimi-code/config.toml` (providers + models blocks)
|
|
57
|
+
|
|
58
|
+
Existing configurations are preserved — NOITON only adds/removes its own entries.
|
|
59
|
+
|
|
60
|
+
## Auto-Install
|
|
61
|
+
|
|
62
|
+
If no agents are detected, NOITON asks what you want to do:
|
|
49
63
|
|
|
50
|
-
|
|
64
|
+
- 💻 **Programar** → installs OpenCode (`curl -fsSL https://opencode.ai/install | bash`)
|
|
65
|
+
- 🤖 **Assistente** → installs Hermes (`pip install nous-hermes`)
|
|
51
66
|
|
|
52
67
|
## Requirements
|
|
53
68
|
|
|
54
69
|
- Node.js >= 18
|
|
55
|
-
-
|
|
70
|
+
- At least one supported agent (or let NOITON install one for you)
|
|
56
71
|
|
|
57
72
|
## License
|
|
58
73
|
|
package/package.json
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "noiton",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "🐙 Universal AI Agent Connector - one key, many agents (OpenCode, Hermes, OpenClaw, Cline, Aider, Kilo, Kimi)",
|
|
5
5
|
"keywords": [
|
|
6
|
+
"noiton",
|
|
6
7
|
"opencode",
|
|
7
|
-
"
|
|
8
|
+
"hermes",
|
|
9
|
+
"openclaw",
|
|
10
|
+
"cline",
|
|
11
|
+
"aider",
|
|
12
|
+
"kilo",
|
|
13
|
+
"kimi",
|
|
14
|
+
"ai",
|
|
8
15
|
"cli",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
16
|
+
"agent",
|
|
17
|
+
"wizard",
|
|
18
|
+
"setup",
|
|
19
|
+
"auth"
|
|
12
20
|
],
|
|
13
21
|
"license": "MIT",
|
|
14
22
|
"author": "NOITON",
|
|
23
|
+
"homepage": "https://github.com/tokensilimitados/noiton",
|
|
15
24
|
"type": "module",
|
|
16
25
|
"bin": {
|
|
17
26
|
"noiton": "./bin/noiton.js"
|
|
@@ -27,11 +36,19 @@
|
|
|
27
36
|
"node": ">=18"
|
|
28
37
|
},
|
|
29
38
|
"dependencies": {
|
|
30
|
-
"@inquirer/prompts": "^7.0.0"
|
|
39
|
+
"@inquirer/prompts": "^7.0.0",
|
|
40
|
+
"@iarna/toml": "^2.2.5",
|
|
41
|
+
"boxen": "^8.0.0",
|
|
42
|
+
"gradient-string": "^3.0.0",
|
|
43
|
+
"json5": "^2.2.3",
|
|
44
|
+
"ora": "^8.0.0",
|
|
45
|
+
"picocolors": "^1.1.0",
|
|
46
|
+
"yaml": "^2.8.4"
|
|
31
47
|
},
|
|
32
48
|
"scripts": {
|
|
33
49
|
"test": "node --test tests/",
|
|
34
|
-
"prepublishOnly": "echo 'no build step - pure JS'"
|
|
50
|
+
"prepublishOnly": "echo 'no build step - pure JS'",
|
|
51
|
+
"view-octopus": "node -e \"import('./src/octopus.js').then(m => console.log(m.octopusHappy()))\""
|
|
35
52
|
},
|
|
36
53
|
"publishConfig": {
|
|
37
54
|
"access": "public",
|
package/src/commands/change.js
CHANGED
|
@@ -1,77 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NOITON change command - swap the API key across all configured agents
|
|
3
|
+
*/
|
|
4
|
+
|
|
1
5
|
import { input, confirm } from "@inquirer/prompts";
|
|
2
|
-
import {
|
|
6
|
+
import { c } from "../constants.js";
|
|
7
|
+
import { printHeader, spinner, ok, fail, info, box, dim } from "../ui.js";
|
|
8
|
+
import { getConfiguredAgents } from "../lib/agents/index.js";
|
|
3
9
|
import { validateKey, maskKey } from "../lib/api.js";
|
|
4
|
-
import {
|
|
5
|
-
readConfig,
|
|
6
|
-
writeConfig,
|
|
7
|
-
hasProvider,
|
|
8
|
-
getProvider,
|
|
9
|
-
upsertProvider,
|
|
10
|
-
buildModels,
|
|
11
|
-
} from "../lib/config.js";
|
|
10
|
+
import { farewellMessage } from "../messages.js";
|
|
12
11
|
|
|
13
|
-
/**
|
|
14
|
-
* Change API key (re-runs wizard with new key).
|
|
15
|
-
*/
|
|
16
12
|
export async function changeCommand() {
|
|
17
|
-
|
|
13
|
+
printHeader("Trocar Chave API");
|
|
18
14
|
|
|
19
|
-
const
|
|
15
|
+
const configured = getConfiguredAgents();
|
|
20
16
|
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
process.exit(1);
|
|
17
|
+
if (configured.length === 0) {
|
|
18
|
+
box("NOITON não está configurado em nenhum agente.\n\nRode 'npx noiton' para configurar.", "warning");
|
|
19
|
+
return;
|
|
25
20
|
}
|
|
26
21
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
console.log(color(" Chave atual: ", "dim") + maskKey(oldKey) + "\n");
|
|
22
|
+
info(`Agentes configurados: ${configured.map(a => a.name).join(", ")}`);
|
|
23
|
+
console.log();
|
|
31
24
|
|
|
32
25
|
const newKey = await input({
|
|
33
|
-
message: " Nova chave:",
|
|
26
|
+
message: " Nova chave NOITON:",
|
|
34
27
|
validate: (v) => (v.trim().length >= 10 ? true : "Chave muito curta"),
|
|
35
28
|
transformer: (v) => maskKey(v),
|
|
36
29
|
});
|
|
37
30
|
|
|
38
|
-
const
|
|
31
|
+
const trimmed = newKey.trim();
|
|
39
32
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const { valid,
|
|
33
|
+
// Validate the new key
|
|
34
|
+
const s = spinner("Validando nova chave...");
|
|
35
|
+
const { valid, error } = await validateKey(trimmed);
|
|
43
36
|
|
|
44
37
|
if (!valid) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
console.log(color(" ✓ Chave válida!\n", "green"));
|
|
50
|
-
|
|
51
|
-
if (!models || models.length === 0) {
|
|
52
|
-
console.log(color(" ⚠ Nenhum modelo disponível para esta chave.\n", "yellow"));
|
|
53
|
-
process.exit(1);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
console.log(color(` 📦 ${models.length} modelo(s) encontrado(s):\n`, "cyan"));
|
|
57
|
-
for (const m of models) {
|
|
58
|
-
console.log(` • ${m.id}`);
|
|
38
|
+
s.fail(`Chave inválida: ${error}`);
|
|
39
|
+
return;
|
|
59
40
|
}
|
|
60
41
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
42
|
+
s.succeed("Nova chave válida!");
|
|
43
|
+
console.log();
|
|
44
|
+
|
|
45
|
+
let success = 0;
|
|
46
|
+
for (const agent of configured) {
|
|
47
|
+
const sub = spinner(`Atualizando ${agent.name}...`);
|
|
48
|
+
try {
|
|
49
|
+
agent.changeKey(trimmed);
|
|
50
|
+
sub.succeed(`${agent.name} atualizado!`);
|
|
51
|
+
success++;
|
|
52
|
+
} catch (err) {
|
|
53
|
+
sub.fail(`${agent.name}: ${err.message}`);
|
|
54
|
+
}
|
|
69
55
|
}
|
|
70
56
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
57
|
+
console.log();
|
|
58
|
+
box(
|
|
59
|
+
success > 0
|
|
60
|
+
? `✨ Chave trocada em ${success} agente(s)!`
|
|
61
|
+
: "⚠️ Nenhum agente pôde ser atualizado.",
|
|
62
|
+
success > 0 ? "success" : "warning"
|
|
63
|
+
);
|
|
74
64
|
|
|
75
|
-
console.log(
|
|
76
|
-
console.log(
|
|
65
|
+
console.log();
|
|
66
|
+
console.log(c.dim(` ${farewellMessage()}`));
|
|
77
67
|
}
|
package/src/commands/init.js
CHANGED
|
@@ -1,85 +1,308 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* NOITON init command - the universal multi-agent wizard
|
|
3
|
+
*
|
|
4
|
+
* Flow:
|
|
5
|
+
* 1. Print banner with octopus mascot
|
|
6
|
+
* 2. Detect all installed agents
|
|
7
|
+
* 3. If OpenCode installed, check version & offer update
|
|
8
|
+
* 4. If no agents, offer to install OpenCode or Hermes (based on use case)
|
|
9
|
+
* 5. Show checklist of detected agents
|
|
10
|
+
* 6. Ask which agents to configure
|
|
11
|
+
* 7. Ask for NOITON API key (once)
|
|
12
|
+
* 8. Validate key + fetch models
|
|
13
|
+
* 9. Ask which model to use as primary (for single-model agents)
|
|
14
|
+
* 10. Configure each selected agent
|
|
15
|
+
* 11. Show funny success message + easter egg
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { input, confirm, select, checkbox } from "@inquirer/prompts";
|
|
19
|
+
import { c } from "../constants.js";
|
|
20
|
+
import {
|
|
21
|
+
printBanner,
|
|
22
|
+
box,
|
|
23
|
+
spinner,
|
|
24
|
+
ok,
|
|
25
|
+
warn,
|
|
26
|
+
fail,
|
|
27
|
+
info,
|
|
28
|
+
dim,
|
|
29
|
+
step,
|
|
30
|
+
checklist,
|
|
31
|
+
divider,
|
|
32
|
+
withSpinner,
|
|
33
|
+
} from "../ui.js";
|
|
34
|
+
import {
|
|
35
|
+
successMessage,
|
|
36
|
+
noAgentMessage,
|
|
37
|
+
thinkingMessage,
|
|
38
|
+
cancelMessage,
|
|
39
|
+
farewellMessage,
|
|
40
|
+
getEasterEgg,
|
|
41
|
+
} from "../messages.js";
|
|
3
42
|
import { validateKey, maskKey } from "../lib/api.js";
|
|
43
|
+
import { getDetectedAgents, getAgent } from "../lib/agents/index.js";
|
|
4
44
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from "../lib/config.js";
|
|
45
|
+
detectAgents,
|
|
46
|
+
getOpenCodeStatus,
|
|
47
|
+
getRecommendedAgent,
|
|
48
|
+
} from "../lib/detect.js";
|
|
49
|
+
import { installAgent, updateAgent, offerInstall } from "../lib/install.js";
|
|
11
50
|
|
|
12
|
-
/**
|
|
13
|
-
* Main wizard command - interactive setup.
|
|
14
|
-
*/
|
|
15
51
|
export async function initCommand() {
|
|
16
|
-
|
|
52
|
+
// ============= STEP 1: BANNER =============
|
|
53
|
+
printBanner("happy");
|
|
54
|
+
|
|
55
|
+
// ============= STEP 2: DETECT AGENTS =============
|
|
56
|
+
step(1, "Procurando agentes de IA instalados...");
|
|
57
|
+
|
|
58
|
+
const detected = getDetectedAgents();
|
|
59
|
+
const opencodeStatus = getOpenCodeStatus();
|
|
60
|
+
|
|
61
|
+
if (detected.length === 0) {
|
|
62
|
+
// ============= STEP 2a: NO AGENTS - OFFER INSTALL =============
|
|
63
|
+
console.log();
|
|
64
|
+
box(noAgentMessage(), "warning");
|
|
65
|
+
console.log();
|
|
66
|
+
|
|
67
|
+
const installChoice = await offerInstall();
|
|
68
|
+
if (!installChoice) {
|
|
69
|
+
console.log();
|
|
70
|
+
info(cancelMessage());
|
|
71
|
+
console.log();
|
|
72
|
+
console.log(c.dim(" 💡 Dica: instale OpenCode ou Hermes e rode noiton novamente!"));
|
|
73
|
+
console.log(c.dim(" OpenCode: curl -fsSL https://opencode.ai/install | bash"));
|
|
74
|
+
console.log(c.dim(" Hermes: pip install nous-hermes"));
|
|
75
|
+
console.log();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Install the chosen agent
|
|
80
|
+
const result = await installAgent(installChoice);
|
|
81
|
+
if (!result.ok) {
|
|
82
|
+
console.log();
|
|
83
|
+
fail(`Não foi possível instalar: ${result.error}`);
|
|
84
|
+
console.log(c.dim(" Tente instalar manualmente e rode noiton novamente."));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Re-detect after install
|
|
89
|
+
const reDetected = getDetectedAgents();
|
|
90
|
+
if (reDetected.length === 0) {
|
|
91
|
+
console.log();
|
|
92
|
+
warn("Instalação concluída, mas não foi possível detectar o agente.");
|
|
93
|
+
info("Reinicie o terminal e rode 'npx noiton' novamente.");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
detected.push(...reDetected);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ============= STEP 2b: CHECK OPENCODE VERSION =============
|
|
100
|
+
if (opencodeStatus?.updateAvailable) {
|
|
101
|
+
console.log();
|
|
102
|
+
box(
|
|
103
|
+
`🔄 OpenCode v${opencodeStatus.latest} disponível!\n` +
|
|
104
|
+
` Você tem v${opencodeStatus.version}.\n\n` +
|
|
105
|
+
` Atualizar agora?`,
|
|
106
|
+
"warning"
|
|
107
|
+
);
|
|
108
|
+
const wantUpdate = await confirm({
|
|
109
|
+
message: "Atualizar OpenCode?",
|
|
110
|
+
default: true,
|
|
111
|
+
});
|
|
112
|
+
if (wantUpdate) {
|
|
113
|
+
const updateResult = await updateAgent("opencode");
|
|
114
|
+
if (updateResult.ok) {
|
|
115
|
+
ok("OpenCode atualizado!");
|
|
116
|
+
} else {
|
|
117
|
+
warn(`Não foi possível atualizar: ${updateResult.error}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ============= STEP 3: SHOW CHECKLIST =============
|
|
123
|
+
step(2, "Agentes detectados");
|
|
124
|
+
|
|
125
|
+
const items = detected.map((a) => ({
|
|
126
|
+
label: a.name,
|
|
127
|
+
ok: true,
|
|
128
|
+
detail: a.version ? `v${a.version}` : "(config encontrado)",
|
|
129
|
+
}));
|
|
130
|
+
checklist(items);
|
|
131
|
+
console.log();
|
|
17
132
|
|
|
18
|
-
|
|
133
|
+
// ============= STEP 4: CHOOSE AGENTS TO CONFIGURE =============
|
|
134
|
+
step(3, "Escolha quais agentes configurar");
|
|
19
135
|
|
|
20
|
-
|
|
21
|
-
|
|
136
|
+
const agentChoices = detected.map((a) => ({
|
|
137
|
+
name: `${a.name}${a.version ? ` (v${a.version})` : ""}`,
|
|
138
|
+
value: a.id,
|
|
139
|
+
checked: true,
|
|
140
|
+
}));
|
|
141
|
+
|
|
142
|
+
let selectedIds;
|
|
143
|
+
if (detected.length === 1) {
|
|
144
|
+
selectedIds = [detected[0].id];
|
|
145
|
+
info(`Configurando: ${detected[0].name}`);
|
|
146
|
+
} else {
|
|
147
|
+
selectedIds = await checkbox({
|
|
148
|
+
message: "Quais agentes você quer conectar ao NOITON?",
|
|
149
|
+
choices: agentChoices,
|
|
150
|
+
required: true,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const selectedAgents = selectedIds
|
|
155
|
+
.map((id) => getAgent(id))
|
|
156
|
+
.filter(Boolean);
|
|
157
|
+
|
|
158
|
+
// ============= STEP 5: CHECK EXISTING CONFIG =============
|
|
159
|
+
const alreadyConfigured = selectedAgents.filter((a) => {
|
|
160
|
+
try {
|
|
161
|
+
return a.isConfigured();
|
|
162
|
+
} catch {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
if (alreadyConfigured.length > 0) {
|
|
168
|
+
console.log();
|
|
169
|
+
warn(
|
|
170
|
+
`NOITON já está configurado em: ${alreadyConfigured.map((a) => a.name).join(", ")}`
|
|
171
|
+
);
|
|
22
172
|
const overwrite = await confirm({
|
|
23
|
-
message: "
|
|
173
|
+
message: "Sobrescrever configuração existente?",
|
|
24
174
|
default: false,
|
|
25
175
|
});
|
|
26
176
|
if (!overwrite) {
|
|
27
|
-
console.log(
|
|
177
|
+
console.log();
|
|
178
|
+
info(cancelMessage());
|
|
28
179
|
return;
|
|
29
180
|
}
|
|
30
181
|
}
|
|
31
182
|
|
|
32
|
-
|
|
183
|
+
// ============= STEP 6: ASK FOR API KEY =============
|
|
184
|
+
step(4, "Cole sua chave NOITON");
|
|
185
|
+
console.log(c.dim(" Uma chave só serve para todos os agentes! 🐙"));
|
|
186
|
+
console.log();
|
|
33
187
|
|
|
34
188
|
const apiKey = await input({
|
|
35
|
-
message: " Chave:",
|
|
189
|
+
message: " Chave NOITON:",
|
|
36
190
|
validate: (v) => (v.trim().length >= 10 ? true : "Chave muito curta"),
|
|
37
191
|
transformer: (v) => maskKey(v),
|
|
38
192
|
});
|
|
39
193
|
|
|
40
194
|
const trimmedKey = apiKey.trim();
|
|
41
195
|
|
|
42
|
-
|
|
43
|
-
|
|
196
|
+
// ============= STEP 7: VALIDATE KEY + FETCH MODELS =============
|
|
197
|
+
console.log();
|
|
198
|
+
const s = spinner(`${thinkingMessage()} Validando chave...`);
|
|
44
199
|
const { valid, models, error } = await validateKey(trimmedKey);
|
|
45
200
|
|
|
46
201
|
if (!valid) {
|
|
47
|
-
|
|
48
|
-
|
|
202
|
+
s.fail(`Erro: ${error}`);
|
|
203
|
+
console.log();
|
|
204
|
+
fail("Não foi possível validar a chave. Verifique e tente novamente.");
|
|
205
|
+
return;
|
|
49
206
|
}
|
|
50
207
|
|
|
51
|
-
|
|
208
|
+
s.succeed("Chave válida!");
|
|
209
|
+
console.log();
|
|
52
210
|
|
|
53
211
|
if (!models || models.length === 0) {
|
|
54
|
-
|
|
55
|
-
|
|
212
|
+
warn("Nenhum modelo disponível para esta chave.");
|
|
213
|
+
return;
|
|
56
214
|
}
|
|
57
215
|
|
|
58
|
-
|
|
216
|
+
// ============= STEP 8: SHOW MODELS =============
|
|
217
|
+
step(5, `Modelos disponíveis (${models.length})`);
|
|
218
|
+
|
|
59
219
|
for (const m of models) {
|
|
60
220
|
const ctx = m.context_window
|
|
61
|
-
?
|
|
221
|
+
? c.dim(` (${Math.round(m.context_window / 1000)}K ctx)`)
|
|
62
222
|
: "";
|
|
63
|
-
console.log(`
|
|
223
|
+
console.log(` ${c.cyan("•")} ${m.id}${ctx}`);
|
|
64
224
|
}
|
|
225
|
+
console.log();
|
|
65
226
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
});
|
|
227
|
+
// ============= STEP 9: CHOOSE PRIMARY MODEL =============
|
|
228
|
+
// For agents that only support one model, ask which to use
|
|
229
|
+
const needsPrimaryModel = selectedAgents.some((a) => !a.supportsMultipleModels);
|
|
70
230
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
231
|
+
let primaryModel = null;
|
|
232
|
+
if (needsPrimaryModel) {
|
|
233
|
+
step(6, "Escolha o modelo principal");
|
|
234
|
+
console.log(c.dim(" Alguns agentes usam apenas 1 modelo por vez."));
|
|
235
|
+
console.log();
|
|
236
|
+
|
|
237
|
+
const modelChoices = models.map((m) => ({
|
|
238
|
+
name: `${m.id}${m.context_window ? ` (${Math.round(m.context_window / 1000)}K ctx)` : ""}`,
|
|
239
|
+
value: m.id,
|
|
240
|
+
}));
|
|
241
|
+
|
|
242
|
+
primaryModel = await select({
|
|
243
|
+
message: "Qual modelo usar como principal?",
|
|
244
|
+
choices: modelChoices,
|
|
245
|
+
default: models[0]?.id,
|
|
246
|
+
});
|
|
247
|
+
console.log();
|
|
74
248
|
}
|
|
75
249
|
|
|
76
|
-
|
|
250
|
+
// ============= STEP 10: CONFIGURE EACH AGENT =============
|
|
251
|
+
step(7, "Configurando agentes...");
|
|
252
|
+
|
|
253
|
+
const results = [];
|
|
254
|
+
for (const agent of selectedAgents) {
|
|
255
|
+
const s = spinner(`Configurando ${agent.name}...`);
|
|
256
|
+
try {
|
|
257
|
+
const result = agent.configure({
|
|
258
|
+
apiKey: trimmedKey,
|
|
259
|
+
models,
|
|
260
|
+
primaryModel,
|
|
261
|
+
});
|
|
262
|
+
s.succeed(`${agent.name} configurado!`);
|
|
263
|
+
results.push({ agent: agent.name, ok: true, ...result });
|
|
264
|
+
} catch (err) {
|
|
265
|
+
s.fail(`Erro em ${agent.name}: ${err.message}`);
|
|
266
|
+
results.push({ agent: agent.name, ok: false, error: err.message });
|
|
267
|
+
}
|
|
268
|
+
}
|
|
77
269
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
270
|
+
// ============= STEP 11: SUMMARY =============
|
|
271
|
+
console.log();
|
|
272
|
+
divider();
|
|
273
|
+
console.log();
|
|
274
|
+
printBanner("dancing");
|
|
275
|
+
|
|
276
|
+
const successCount = results.filter((r) => r.ok).length;
|
|
277
|
+
if (successCount > 0) {
|
|
278
|
+
box(
|
|
279
|
+
`${successMessage()}\n\n` +
|
|
280
|
+
`${successCount} de ${selectedAgents.length} agente(s) configurado(s):`,
|
|
281
|
+
"success"
|
|
282
|
+
);
|
|
283
|
+
console.log();
|
|
284
|
+
for (const r of results) {
|
|
285
|
+
if (r.ok) {
|
|
286
|
+
ok(`${r.agent} ${c.dim(`→ ${r.path}`)}`);
|
|
287
|
+
} else {
|
|
288
|
+
fail(`${r.agent} ${c.dim(`→ ${r.error}`)}`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
} else {
|
|
292
|
+
box("Nenhum agente foi configurado. Tente novamente!", "error");
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// ============= STEP 12: EASTER EGG + FAREWELL =============
|
|
297
|
+
const egg = getEasterEgg();
|
|
298
|
+
if (egg) {
|
|
299
|
+
console.log();
|
|
300
|
+
console.log(c.yellow(` 🎁 ${egg}`));
|
|
301
|
+
}
|
|
81
302
|
|
|
82
|
-
console.log(
|
|
83
|
-
console.log(
|
|
84
|
-
console.log(
|
|
303
|
+
console.log();
|
|
304
|
+
console.log(c.dim(" 💡 Reinicie os agentes para aplicar as mudanças."));
|
|
305
|
+
console.log();
|
|
306
|
+
console.log(c.purple(` ${farewellMessage()}`));
|
|
307
|
+
console.log();
|
|
85
308
|
}
|