@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.
- package/CHANGELOG.md +60 -0
- package/README.md +38 -3
- package/dist/commands/admin/sdk-credential.js +3 -1
- package/dist/commands/ai-models.d.ts +2 -1
- package/dist/commands/ai-models.js +4 -5
- package/dist/commands/ai.d.ts +12 -2
- package/dist/commands/ai.js +47 -38
- package/dist/commands/auth.d.ts +3 -2
- package/dist/commands/auth.js +96 -57
- package/dist/commands/build.js +35 -4
- package/dist/commands/chat.d.ts +24 -6
- package/dist/commands/chat.js +43 -7
- package/dist/commands/code.js +11 -2
- package/dist/commands/config.js +15 -13
- package/dist/commands/db-frontdoor.js +10 -5
- package/dist/commands/db.d.ts +8 -2
- package/dist/commands/db.js +13 -6
- package/dist/commands/deploy.d.ts +14 -5
- package/dist/commands/deploy.js +376 -55
- package/dist/commands/dev-context.js +1 -1
- package/dist/commands/environments-repoint.d.ts +49 -0
- package/dist/commands/environments-repoint.js +219 -0
- package/dist/commands/init.js +7 -1
- package/dist/commands/new.js +14 -0
- package/dist/commands/secrets.d.ts +6 -4
- package/dist/commands/secrets.js +14 -7
- package/dist/commands/ui.js +1 -1
- package/dist/commands/workspaces.js +16 -1
- package/dist/index.js +47 -7
- package/dist/lib/ai/auth-discovery.d.ts +9 -12
- package/dist/lib/ai/auth-discovery.js +43 -145
- package/dist/lib/ai/orchestrator.d.ts +13 -6
- package/dist/lib/ai/orchestrator.js +46 -246
- package/dist/lib/ai/provedores.d.ts +57 -0
- package/dist/lib/ai/provedores.js +66 -0
- package/dist/lib/build-targets.d.ts +48 -10
- package/dist/lib/build-targets.js +64 -10
- package/dist/lib/cli-write.js +6 -3
- package/dist/lib/code-agent-gateway.d.ts +2 -2
- package/dist/lib/code-agent-gateway.js +2 -2
- package/dist/lib/code-agent-settings.d.ts +2 -2
- package/dist/lib/code-agent-settings.js +2 -4
- package/dist/lib/code-agent-types.d.ts +3 -1
- package/dist/lib/config.d.ts +4 -7
- package/dist/lib/config.js +9 -6
- package/dist/lib/deploy-recusa-de-destino.d.ts +9 -0
- package/dist/lib/deploy-recusa-de-destino.js +98 -0
- package/dist/lib/deploy-render-probe.d.ts +117 -0
- package/dist/lib/deploy-render-probe.js +475 -0
- package/dist/lib/deploy-vm-um-app.d.ts +62 -0
- package/dist/lib/deploy-vm-um-app.js +83 -0
- package/dist/lib/segredo-produto.d.ts +25 -5
- package/dist/lib/segredo-produto.js +45 -10
- package/dist/lib/sse.d.ts +4 -5
- package/dist/lib/sse.js +4 -5
- package/package.json +1 -2
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Auth auto-discovery —
|
|
3
|
-
*
|
|
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
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
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
|
|
17
|
-
*
|
|
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
|
|
30
|
-
// (
|
|
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
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
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
|
|
181
|
-
const
|
|
182
|
-
const
|
|
183
|
-
|
|
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
|
|
187
|
-
|
|
188
|
-
npmPackage: '@google/gemini-cli',
|
|
189
|
-
installed,
|
|
131
|
+
provider,
|
|
132
|
+
installed: false,
|
|
190
133
|
credentialSource: 'env',
|
|
191
|
-
apiKey:
|
|
192
|
-
hint:
|
|
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
|
|
225
|
-
|
|
226
|
-
npmPackage: '@google/gemini-cli',
|
|
227
|
-
installed,
|
|
139
|
+
provider,
|
|
140
|
+
installed: false,
|
|
228
141
|
credentialSource: null,
|
|
229
|
-
hint:
|
|
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
|
-
*
|
|
236
|
-
*
|
|
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
|
-
|
|
244
|
-
|
|
245
|
-
|
|
149
|
+
const DETECTORES = {
|
|
150
|
+
groq: () => detectApenasChave('groq'),
|
|
151
|
+
nvidia: () => detectApenasChave('nvidia'),
|
|
152
|
+
openai: detectOpenAI,
|
|
153
|
+
};
|
|
246
154
|
/**
|
|
247
|
-
*
|
|
248
|
-
*
|
|
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
|
|
253
|
-
|
|
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
|
|
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
|
|
170
|
+
return out;
|
|
273
171
|
}
|
|
274
172
|
/**
|
|
275
173
|
* Tenta instalar globalmente um pacote via npm. Bloqueante, com output
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
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 =
|
|
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 →
|
|
36
|
-
* 3. Sumarização rápida / Q&A factual → Groq (mais rápido)
|
|
37
|
-
* 4.
|
|
38
|
-
*
|
|
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
|
/**
|