@neetru/cli 2.33.0 → 2.34.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +38 -3
  3. package/dist/commands/admin/sdk-credential.js +3 -1
  4. package/dist/commands/ai-models.d.ts +2 -1
  5. package/dist/commands/ai-models.js +4 -5
  6. package/dist/commands/ai.d.ts +12 -2
  7. package/dist/commands/ai.js +47 -38
  8. package/dist/commands/auth.d.ts +3 -2
  9. package/dist/commands/auth.js +96 -57
  10. package/dist/commands/build.js +35 -4
  11. package/dist/commands/chat.d.ts +24 -6
  12. package/dist/commands/chat.js +43 -7
  13. package/dist/commands/code.js +11 -2
  14. package/dist/commands/config.js +15 -13
  15. package/dist/commands/db-frontdoor.js +10 -5
  16. package/dist/commands/db.d.ts +8 -2
  17. package/dist/commands/db.js +13 -6
  18. package/dist/commands/deploy.d.ts +14 -5
  19. package/dist/commands/deploy.js +376 -55
  20. package/dist/commands/dev-context.js +1 -1
  21. package/dist/commands/environments-repoint.d.ts +49 -0
  22. package/dist/commands/environments-repoint.js +219 -0
  23. package/dist/commands/init.js +7 -1
  24. package/dist/commands/new.js +14 -0
  25. package/dist/commands/secrets.d.ts +6 -4
  26. package/dist/commands/secrets.js +14 -7
  27. package/dist/commands/ui.js +1 -1
  28. package/dist/commands/workspaces.js +16 -1
  29. package/dist/index.js +47 -7
  30. package/dist/lib/ai/auth-discovery.d.ts +9 -12
  31. package/dist/lib/ai/auth-discovery.js +43 -145
  32. package/dist/lib/ai/orchestrator.d.ts +13 -6
  33. package/dist/lib/ai/orchestrator.js +46 -246
  34. package/dist/lib/ai/provedores.d.ts +57 -0
  35. package/dist/lib/ai/provedores.js +66 -0
  36. package/dist/lib/build-targets.d.ts +48 -10
  37. package/dist/lib/build-targets.js +64 -10
  38. package/dist/lib/cli-write.js +6 -3
  39. package/dist/lib/code-agent-gateway.d.ts +2 -2
  40. package/dist/lib/code-agent-gateway.js +2 -2
  41. package/dist/lib/code-agent-settings.d.ts +2 -2
  42. package/dist/lib/code-agent-settings.js +2 -4
  43. package/dist/lib/code-agent-types.d.ts +3 -1
  44. package/dist/lib/config.d.ts +4 -7
  45. package/dist/lib/config.js +9 -6
  46. package/dist/lib/deploy-recusa-de-destino.d.ts +9 -0
  47. package/dist/lib/deploy-recusa-de-destino.js +98 -0
  48. package/dist/lib/deploy-render-probe.d.ts +117 -0
  49. package/dist/lib/deploy-render-probe.js +475 -0
  50. package/dist/lib/deploy-vm-um-app.d.ts +62 -0
  51. package/dist/lib/deploy-vm-um-app.js +83 -0
  52. package/dist/lib/segredo-produto.d.ts +25 -5
  53. package/dist/lib/segredo-produto.js +45 -10
  54. package/dist/lib/sse.d.ts +4 -5
  55. package/dist/lib/sse.js +4 -5
  56. package/package.json +1 -2
@@ -1,33 +1,33 @@
1
1
  /**
2
- * Auth auto-discovery — detecta Claude Code, Codex (OpenAI) e Gemini CLIs
3
- * já instalados na máquina e tenta extrair credenciais existentes.
2
+ * Auth auto-discovery — procura chave já existente na máquina para cada
3
+ * provedor da lista única (`provedores.ts`), sem mexer em nada (read-only).
4
4
  *
5
- * Motivação: usuário não deveria precisar setar `anthropicApiKey` na mão se
6
- * ele já tem `claude` (Claude Code) ou `codex` (OpenAI Codex CLI) ou `gemini`
7
- * (Google Gemini CLI) instalados e logados. CLI Neetru reaproveita as creds
8
- * pra ligar o `neetru ai` direto.
5
+ * - Groq e NVIDIA NIM: só chave de API, lida do ambiente (GROQ_API_KEY,
6
+ * NVIDIA_API_KEY). Não há programa para instalar.
7
+ * - OpenAI: a variável OPENAI_API_KEY ou o arquivo do Codex (`codex`, o
8
+ * programa de linha de comando da OpenAI) em ~/.codex/auth.json.
9
9
  *
10
- * Estratégia (cross-platform Windows/macOS/Linux):
11
- * 1. Detectar binário no PATH (`where` no Windows, `command -v` no POSIX).
12
- * 2. Olhar locais conhecidos de config (~/.claude, ~/.codex, ~/.config/gemini).
13
- * 3. Olhar env vars (ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY).
14
- * 4. Reporta o que está disponível sem mexer em nada (read-only).
10
+ * bug_19d312f3: a descoberta lia também ANTHROPIC_API_KEY, GEMINI_API_KEY,
11
+ * GOOGLE_API_KEY e os arquivos do Claude Code e do Gemini, e o `neetru ai` saía
12
+ * usando essas chaves sem o dev escolher. Anthropic e Gemini estão vetados pela
13
+ * casa e saíram da lista; a descoberta não procura mais as chaves deles.
15
14
  *
16
- * O `setup wizard` (em commands/auth.ts) usa essa detecção pra ofertar
17
- * install + login per-provider.
15
+ * O assistente do `neetru auth setup` (commands/auth.ts) usa esta detecção
16
+ * para mostrar o estado de cada provedor e pedir a chave que falta.
18
17
  */
19
18
  import { execSync, execFileSync } from 'node:child_process';
20
19
  import { existsSync, readFileSync } from 'node:fs';
21
20
  import { homedir, platform } from 'node:os';
22
21
  import { join } from 'node:path';
22
+ import { CHAVE_DO_PROVEDOR, PROVEDORES_IA, VARIAVEL_DO_PROVEDOR, } from './provedores.js';
23
23
  const IS_WINDOWS = platform() === 'win32';
24
24
  /**
25
25
  * Checa se um binário existe no PATH. Cross-platform via `where` (Windows)
26
26
  * e `command -v` (POSIX). Silencioso — captura erro e retorna false.
27
27
  */
28
28
  function binaryExists(name) {
29
- // Defesa em profundidade: hoje `name` vem de uma lista interna fixa
30
- // (claude/codex/gemini), mas validamos o formato e evitamos o shell para que
29
+ // Defesa em profundidade: hoje `name` vem de uma constante interna
30
+ // (`codex`), mas validamos o formato e evitamos o shell para que
31
31
  // isto NUNCA permita injeção de comando, mesmo se a fonte do nome mudar.
32
32
  if (!/^[A-Za-z0-9._-]+$/.test(name))
33
33
  return false;
@@ -64,60 +64,6 @@ function readJsonSafe(path) {
64
64
  return null;
65
65
  }
66
66
  }
67
- /**
68
- * Anthropic / Claude Code.
69
- * - Binário: `claude` (instalado via npm i -g @anthropic-ai/claude-code)
70
- * - Config: ~/.claude/.credentials.json (oauth token OU api key)
71
- * - Env: ANTHROPIC_API_KEY
72
- */
73
- function detectAnthropic() {
74
- const home = homedir();
75
- const installed = binaryExists('claude');
76
- // Prioridade 1: env var (mais simples — Anthropic SDK aceita direto)
77
- const envKey = process.env.ANTHROPIC_API_KEY;
78
- if (envKey && envKey.startsWith('sk-ant-')) {
79
- return {
80
- provider: 'anthropic',
81
- binary: 'claude',
82
- npmPackage: '@anthropic-ai/claude-code',
83
- installed,
84
- credentialSource: 'env',
85
- apiKey: envKey,
86
- hint: 'usando ANTHROPIC_API_KEY do ambiente',
87
- };
88
- }
89
- // Prioridade 2: arquivo de credentials do Claude Code
90
- const credsPath = join(home, '.claude', '.credentials.json');
91
- const creds = readJsonSafe(credsPath);
92
- if (creds) {
93
- // Claude Code armazena `apiKey` ou tokens OAuth. Só populamos apiKey se for sk-ant.
94
- const maybeKey = typeof creds.apiKey === 'string' && creds.apiKey.startsWith('sk-ant-')
95
- ? creds.apiKey
96
- : undefined;
97
- return {
98
- provider: 'anthropic',
99
- binary: 'claude',
100
- npmPackage: '@anthropic-ai/claude-code',
101
- installed,
102
- credentialSource: 'binary-config',
103
- credentialPath: credsPath,
104
- apiKey: maybeKey,
105
- hint: maybeKey
106
- ? `extraindo apiKey de ${credsPath}`
107
- : `Claude Code logado via OAuth (sem apiKey plaintext) — rode "claude /login" e setting ANTHROPIC_API_KEY ou use "neetru config set anthropicApiKey"`,
108
- };
109
- }
110
- return {
111
- provider: 'anthropic',
112
- binary: 'claude',
113
- npmPackage: '@anthropic-ai/claude-code',
114
- installed,
115
- credentialSource: null,
116
- hint: installed
117
- ? 'Claude Code instalado mas sem credenciais — rode "claude" pra logar'
118
- : 'instalar: npm i -g @anthropic-ai/claude-code',
119
- };
120
- }
121
67
  /**
122
68
  * OpenAI / Codex CLI.
123
69
  * - Binário: `codex` (npm i -g @openai/codex)
@@ -172,96 +118,48 @@ function detectOpenAI() {
172
118
  };
173
119
  }
174
120
  /**
175
- * Google / Gemini CLI.
176
- * - Binário: `gemini` (npm i -g @google/gemini-cli)
177
- * - Config: ~/.config/gemini/auth.json (Linux/macOS) ou %APPDATA%\gemini\auth.json (Windows)
178
- * - Env: GEMINI_API_KEY ou GOOGLE_API_KEY
121
+ * Groq e NVIDIA NIM — provedores OpenAI-compatible, só de chave de API. A
122
+ * descoberta lê só a variável de ambiente (GROQ_API_KEY / NVIDIA_API_KEY). O
123
+ * valor PODE ser um pool separado por vírgula; aqui vai cru e o orchestrator
124
+ * separa.
179
125
  */
180
- function detectGemini() {
181
- const home = homedir();
182
- const installed = binaryExists('gemini');
183
- const envKey = process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY;
184
- if (envKey) {
126
+ function detectApenasChave(provider) {
127
+ const variavel = VARIAVEL_DO_PROVEDOR[provider];
128
+ const valor = process.env[variavel];
129
+ if (valor) {
185
130
  return {
186
- provider: 'gemini',
187
- binary: 'gemini',
188
- npmPackage: '@google/gemini-cli',
189
- installed,
131
+ provider,
132
+ installed: false,
190
133
  credentialSource: 'env',
191
- apiKey: envKey,
192
- hint: 'usando GEMINI_API_KEY (ou GOOGLE_API_KEY) do ambiente',
193
- };
194
- }
195
- const candidates = IS_WINDOWS
196
- ? [
197
- join(process.env.APPDATA ?? join(home, 'AppData', 'Roaming'), 'gemini', 'auth.json'),
198
- join(home, '.config', 'gemini', 'auth.json'),
199
- ]
200
- : [join(home, '.config', 'gemini', 'auth.json')];
201
- for (const path of candidates) {
202
- const auth = readJsonSafe(path);
203
- if (!auth)
204
- continue;
205
- const maybeKey = typeof auth.apiKey === 'string'
206
- ? auth.apiKey
207
- : typeof auth.GEMINI_API_KEY === 'string'
208
- ? auth.GEMINI_API_KEY
209
- : undefined;
210
- return {
211
- provider: 'gemini',
212
- binary: 'gemini',
213
- npmPackage: '@google/gemini-cli',
214
- installed,
215
- credentialSource: 'binary-config',
216
- credentialPath: path,
217
- apiKey: maybeKey,
218
- hint: maybeKey
219
- ? `extraindo apiKey de ${path}`
220
- : `Gemini logado mas sem apiKey plaintext — rode "gemini auth" com --api-key ou exporte GEMINI_API_KEY`,
134
+ apiKey: valor,
135
+ hint: `usando ${variavel} do ambiente`,
221
136
  };
222
137
  }
223
138
  return {
224
- provider: 'gemini',
225
- binary: 'gemini',
226
- npmPackage: '@google/gemini-cli',
227
- installed,
139
+ provider,
140
+ installed: false,
228
141
  credentialSource: null,
229
- hint: installed
230
- ? 'Gemini instalado mas sem credenciais — rode "gemini auth"'
231
- : 'instalar: npm i -g @google/gemini-cli',
142
+ hint: `sem chave — exporte ${variavel} ou rode "neetru config set ${CHAVE_DO_PROVEDOR[provider]} <chave>"`,
232
143
  };
233
144
  }
234
145
  /**
235
- * Detecta todos os providers conhecidos. Read-only — não escreve nada,
236
- * não chama API. Seguro pra rodar em startup do `neetru ai`.
237
- *
238
- * Cobre só os providers que têm CLI concorrente (claude/codex/gemini) — o
239
- * wizard de setup usa esta lista pra ofertar install/login per-binário.
240
- * Groq e NVIDIA NIM são API-key-only (sem CLI pra instalar); a descoberta
241
- * deles vive em `discoveredKeys` (env direto).
146
+ * Um detector por provedor da lista única. O `Record<ProvedorIa, …>` faz o tsc
147
+ * recusar provedor novo em `PROVEDORES_IA` sem detector aqui.
242
148
  */
243
- export function detectAllProviders() {
244
- return [detectAnthropic(), detectOpenAI(), detectGemini()];
245
- }
149
+ const DETECTORES = {
150
+ groq: () => detectApenasChave('groq'),
151
+ nvidia: () => detectApenasChave('nvidia'),
152
+ openai: detectOpenAI,
153
+ };
246
154
  /**
247
- * Groq + NVIDIA NIM — providers OpenAI-compatible, API-key-only. Descoberta
248
- * só por env var (GROQ_API_KEY / NVIDIA_API_KEY). O env PODE conter um pool
249
- * comma-separated; aqui devolvemos o valor cru e o orchestrator parseia.
250
- * Não disrupta o wizard de binários (detectAllProviders).
155
+ * Estado de cada provedor da lista única, na ordem dela. Read-only — não
156
+ * escreve nada, não chama API. Seguro pra rodar em startup do `neetru ai`.
251
157
  */
252
- function discoverApiOnlyKeys() {
253
- const out = {};
254
- const groq = process.env.GROQ_API_KEY;
255
- const nvidia = process.env.NVIDIA_API_KEY;
256
- if (groq)
257
- out.groq = groq;
258
- if (nvidia)
259
- out.nvidia = nvidia;
260
- return out;
158
+ export function detectAllProviders() {
159
+ return PROVEDORES_IA.map((p) => DETECTORES[p]());
261
160
  }
262
161
  /**
263
- * Conveniência: retorna apenas providers com apiKey extraída (pronta pra usar).
264
- * Inclui os CLI-discoverable (claude/codex/gemini) + os API-key-only (groq/nvidia).
162
+ * Conveniência: retorna apenas os provedores com chave achada (pronta pra usar).
265
163
  */
266
164
  export function discoveredKeys() {
267
165
  const out = {};
@@ -269,7 +167,7 @@ export function discoveredKeys() {
269
167
  if (p.apiKey)
270
168
  out[p.provider] = p.apiKey;
271
169
  }
272
- return { ...out, ...discoverApiOnlyKeys() };
170
+ return out;
273
171
  }
274
172
  /**
275
173
  * Tenta instalar globalmente um pacote via npm. Bloqueante, com output
@@ -1,6 +1,7 @@
1
- export type ModelId = 'claude' | 'openai' | 'gemini' | 'groq' | 'nvidia' | 'gateway' | 'auto';
1
+ import { type ModeloDoAi, type ProvedorIa } from './provedores.js';
2
+ export type ModelId = ModeloDoAi;
2
3
  /** Modelo concreto já resolvido (sem 'auto'). */
3
- export type ResolvedModel = 'claude' | 'openai' | 'gemini' | 'groq' | 'nvidia' | 'gateway';
4
+ export type ResolvedModel = ProvedorIa | 'gateway';
4
5
  export interface Message {
5
6
  role: 'user' | 'assistant';
6
7
  content: string;
@@ -32,10 +33,16 @@ export declare function parseKeyPool(raw: string | undefined | null): string[];
32
33
  *
33
34
  * Heurísticas (em ordem):
34
35
  * 1. Se user forçou um modelo (!= auto), respeita — desde que tenha cred.
35
- * 2. Code generation pesado → OpenAI (gpt-4.1); senão NVIDIA NIM (llama-70b).
36
- * 3. Sumarização rápida / Q&A factual → Groq (mais rápido); senão Gemini.
37
- * 4. Default: Claude (arquitetura, análise, raciocínio longo).
38
- * 5. Fallback: primeiro provider com cred (claude > openai > gemini > groq > nvidia).
36
+ * 2. Code generation pesado → NVIDIA NIM (llama-70b, gratuito).
37
+ * 3. Sumarização rápida / Q&A factual → Groq (mais rápido).
38
+ * 4. Fallback: primeiro provider com cred, gratuitos primeiro
39
+ * (groq > nvidia > openai).
40
+ *
41
+ * bug_19d312f3: o default era Claude (API da Anthropic) e o Q&A rápido caía no
42
+ * Gemini quando faltava o Groq. Os dois saíram da lista única (vetados).
43
+ * Revisão do #104: o `auto` preferia a OpenAI (paga) na geração de código e no
44
+ * fallback, à frente do Groq e da NVIDIA. Agora ela só entra no `auto` quando
45
+ * nenhum provedor gratuito tem chave; quem a quer antes pede com `-m openai`.
39
46
  */
40
47
  export declare function routeModel(input: string, preferred: ModelId): ResolvedModel;
41
48
  /**