@neetru/cli 2.13.1 → 2.15.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 (61) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/commands/ai.js +8 -8
  3. package/dist/commands/autocomplete.d.ts +1 -1
  4. package/dist/commands/autocomplete.js +1 -0
  5. package/dist/commands/autocomplete.js.map +1 -1
  6. package/dist/commands/code.d.ts +27 -0
  7. package/dist/commands/code.js +469 -0
  8. package/dist/commands/code.js.map +1 -0
  9. package/dist/commands/fn.d.ts +6 -0
  10. package/dist/commands/fn.js +88 -0
  11. package/dist/commands/fn.js.map +1 -0
  12. package/dist/commands/init.js +147 -147
  13. package/dist/commands/marketplace.d.ts +36 -0
  14. package/dist/commands/marketplace.js +585 -0
  15. package/dist/commands/marketplace.js.map +1 -0
  16. package/dist/commands/ui.d.ts +1 -1
  17. package/dist/commands/ui.js +9 -0
  18. package/dist/commands/ui.js.map +1 -1
  19. package/dist/index.js +19 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/lib/ai/context.js +91 -91
  22. package/dist/lib/ai/orchestrator.js +7 -43
  23. package/dist/lib/ai/orchestrator.js.map +1 -1
  24. package/dist/lib/api-client.d.ts +1 -0
  25. package/dist/lib/api-client.js +4 -3
  26. package/dist/lib/api-client.js.map +1 -1
  27. package/dist/lib/code-agent-files.d.ts +47 -0
  28. package/dist/lib/code-agent-files.js +468 -0
  29. package/dist/lib/code-agent-files.js.map +1 -0
  30. package/dist/lib/code-agent-gateway.d.ts +27 -0
  31. package/dist/lib/code-agent-gateway.js +115 -0
  32. package/dist/lib/code-agent-gateway.js.map +1 -0
  33. package/dist/lib/code-agent-protocol.d.ts +24 -0
  34. package/dist/lib/code-agent-protocol.js +56 -0
  35. package/dist/lib/code-agent-protocol.js.map +1 -0
  36. package/dist/lib/code-agent-session.d.ts +54 -0
  37. package/dist/lib/code-agent-session.js +147 -0
  38. package/dist/lib/code-agent-session.js.map +1 -0
  39. package/dist/lib/code-agent-settings.d.ts +20 -0
  40. package/dist/lib/code-agent-settings.js +38 -0
  41. package/dist/lib/code-agent-settings.js.map +1 -0
  42. package/dist/lib/code-agent-tools.d.ts +17 -0
  43. package/dist/lib/code-agent-tools.js +52 -0
  44. package/dist/lib/code-agent-tools.js.map +1 -0
  45. package/dist/lib/code-agent-types.d.ts +34 -0
  46. package/dist/lib/code-agent-types.js +7 -0
  47. package/dist/lib/code-agent-types.js.map +1 -0
  48. package/dist/lib/code-agent-ui.d.ts +30 -0
  49. package/dist/lib/code-agent-ui.js +258 -0
  50. package/dist/lib/code-agent-ui.js.map +1 -0
  51. package/dist/lib/sse.d.ts +14 -0
  52. package/dist/lib/sse.js +43 -0
  53. package/dist/lib/sse.js.map +1 -0
  54. package/package.json +1 -1
  55. package/templates/auth/callback.ts +22 -22
  56. package/templates/auth/sign-in.tsx +41 -41
  57. package/templates/billing/checkout.ts +22 -22
  58. package/templates/billing/page.tsx +43 -43
  59. package/templates/support/ticket-form.tsx +68 -68
  60. package/templates/usage/track.ts +30 -30
  61. package/templates/users/profile.tsx +43 -43
@@ -0,0 +1,468 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { spawnSync } from 'node:child_process';
4
+ const DEFAULT_IGNORES = new Set([
5
+ '.git',
6
+ '.hg',
7
+ '.svn',
8
+ 'node_modules',
9
+ '.next',
10
+ 'dist',
11
+ 'build',
12
+ 'coverage',
13
+ '.turbo',
14
+ ]);
15
+ const MAX_FILE_BYTES = 250_000;
16
+ const MAX_FILE_CHARS = 40_000;
17
+ const MAX_LIST_FILES = 300;
18
+ const MAX_SEARCH_MATCHES = 80;
19
+ const MAX_TOOL_OUTPUT_CHARS = 60_000;
20
+ // Fase 3 (NEETRU_CODE_ARCHITECTURE.md): limites das ferramentas produtivas.
21
+ const MAX_READ_MANY_FILES = 20;
22
+ const MAX_REGEX_PATTERN_CHARS = 200;
23
+ const MAX_REGEX_LINE_CHARS = 2_000; // pula linhas absurdamente longas (ex: minificado) — reduz risco de ReDoS.
24
+ const MAX_SYMBOL_FILES = 200;
25
+ const MAX_SYMBOLS = 300;
26
+ const RUN_TESTS_TIMEOUT_MS = 120_000;
27
+ function normalizeForCompare(value) {
28
+ return process.platform === 'win32' ? value.toLowerCase() : value;
29
+ }
30
+ function isInside(root, target) {
31
+ const rootCmp = normalizeForCompare(root);
32
+ const targetCmp = normalizeForCompare(target);
33
+ return targetCmp === rootCmp || targetCmp.startsWith(`${rootCmp}${path.sep}`);
34
+ }
35
+ export function resolveInside(rootDir, inputPath) {
36
+ const root = path.resolve(rootDir);
37
+ const resolved = path.resolve(root, inputPath);
38
+ if (!isInside(root, resolved)) {
39
+ throw new Error(`Path fora do cwd: ${inputPath}`);
40
+ }
41
+ // Contenção lexical nao basta: um symlink/junction DENTRO do cwd pode
42
+ // apontar pra fora (ex: `leak -> ~/.config/neetru-cli/auth.json`) e vazar
43
+ // pro contexto do gateway. Resolve o path real e reconfirma a contencao —
44
+ // só roda se o arquivo existir (achado do Codex review 2026-07-09).
45
+ if (fs.existsSync(resolved)) {
46
+ const realRoot = fs.realpathSync(root);
47
+ const realResolved = fs.realpathSync(resolved);
48
+ if (!isInside(realRoot, realResolved)) {
49
+ throw new Error(`Path fora do cwd (symlink aponta pra fora): ${inputPath}`);
50
+ }
51
+ }
52
+ return resolved;
53
+ }
54
+ function toRelative(rootDir, fullPath) {
55
+ return path.relative(path.resolve(rootDir), fullPath).replace(/\\/g, '/');
56
+ }
57
+ // Arquivos que tipicamente carregam segredo bruto — bloqueados mesmo dentro
58
+ // do cwd. Path injection pelo modelo (README/issue com NEETRU_TOOL embutido)
59
+ // nao consegue fazer a IA ler .env/chave/credencial e mandar de volta pro
60
+ // gateway (achado do Codex review 2026-07-09).
61
+ const SECRET_PATH_PATTERN = /(^|[\\/])(\.env(\..+)?|[^\\/]+\.(pem|key|pfx|p12)|id_rsa\w*|id_ed25519\w*|credentials\.json|service[-_]?account.*\.json)$/i;
62
+ function isSecretPath(relativePath) {
63
+ return SECRET_PATH_PATTERN.test(relativePath);
64
+ }
65
+ // Redação defense-in-depth: mesmo em arquivos "normais", uma linha com cara
66
+ // de segredo hardcoded nao vai pro contexto do gateway em texto claro.
67
+ const SECRET_LINE_PATTERN = /((?:api[_-]?key|secret|token|password|passwd)\s*[:=]\s*['"]?)([A-Za-z0-9_\-.\/+]{12,})/gi;
68
+ export function redactSecrets(content) {
69
+ return content.replace(SECRET_LINE_PATTERN, '$1[REDACTED]');
70
+ }
71
+ function clipToolOutput(label, content, maxChars = MAX_TOOL_OUTPUT_CHARS) {
72
+ if (content.length <= maxChars)
73
+ return content;
74
+ return `${content.slice(0, maxChars)}\n\n[TRUNCADO: ${label} maior que ${maxChars} chars]`;
75
+ }
76
+ function runGit(rootDir, args) {
77
+ const result = spawnSync('git', args, { cwd: rootDir, encoding: 'utf8' });
78
+ return {
79
+ ok: result.status === 0,
80
+ stdout: result.stdout ?? '',
81
+ stderr: result.stderr ?? '',
82
+ };
83
+ }
84
+ export function readFileContext(rootDir, inputPath) {
85
+ const fullPath = resolveInside(rootDir, inputPath);
86
+ const relative = toRelative(rootDir, fullPath);
87
+ if (isSecretPath(relative)) {
88
+ throw new Error(`Leitura bloqueada: "${relative}" parece conter segredo (.env/chave/credencial). ` +
89
+ 'Cole o trecho necessario manualmente se precisar que a IA veja.');
90
+ }
91
+ const stat = fs.statSync(fullPath);
92
+ if (!stat.isFile())
93
+ throw new Error(`Nao e arquivo: ${inputPath}`);
94
+ if (stat.size > MAX_FILE_BYTES) {
95
+ throw new Error(`Arquivo muito grande para contexto: ${inputPath} (${stat.size} bytes)`);
96
+ }
97
+ const content = redactSecrets(fs.readFileSync(fullPath, 'utf8'));
98
+ const clipped = content.length > MAX_FILE_CHARS
99
+ ? `${content.slice(0, MAX_FILE_CHARS)}\n\n[TRUNCADO: arquivo maior que ${MAX_FILE_CHARS} chars]`
100
+ : content;
101
+ return `--- ${relative} ---\n${clipped}`;
102
+ }
103
+ function walkFiles(rootDir) {
104
+ const out = [];
105
+ function walk(dir) {
106
+ if (out.length >= MAX_LIST_FILES)
107
+ return;
108
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
109
+ if (DEFAULT_IGNORES.has(entry.name))
110
+ continue;
111
+ const full = path.join(dir, entry.name);
112
+ if (entry.isDirectory()) {
113
+ walk(full);
114
+ }
115
+ else if (entry.isFile()) {
116
+ out.push(toRelative(rootDir, full));
117
+ }
118
+ if (out.length >= MAX_LIST_FILES)
119
+ return;
120
+ }
121
+ }
122
+ walk(path.resolve(rootDir));
123
+ return out;
124
+ }
125
+ export function listFiles(rootDir, pattern = '') {
126
+ const git = spawnSync('git', ['ls-files'], { cwd: rootDir, encoding: 'utf8' });
127
+ let files = git.status === 0
128
+ ? git.stdout.split(/\r?\n/).filter(Boolean)
129
+ : walkFiles(rootDir);
130
+ const needle = pattern.trim().toLowerCase();
131
+ if (needle)
132
+ files = files.filter((file) => file.toLowerCase().includes(needle));
133
+ return files.slice(0, MAX_LIST_FILES);
134
+ }
135
+ export function searchFiles(rootDir, query) {
136
+ const needle = query;
137
+ if (!needle)
138
+ return [];
139
+ const matches = [];
140
+ for (const file of listFiles(rootDir)) {
141
+ if (matches.length >= MAX_SEARCH_MATCHES)
142
+ break;
143
+ if (isSecretPath(file))
144
+ continue;
145
+ try {
146
+ const full = resolveInside(rootDir, file);
147
+ const stat = fs.statSync(full);
148
+ if (!stat.isFile() || stat.size > MAX_FILE_BYTES)
149
+ continue;
150
+ const lines = redactSecrets(fs.readFileSync(full, 'utf8')).split(/\r?\n/);
151
+ for (let i = 0; i < lines.length; i++) {
152
+ if (lines[i].includes(needle)) {
153
+ matches.push(`${file}:${i + 1}: ${lines[i].slice(0, 240)}`);
154
+ if (matches.length >= MAX_SEARCH_MATCHES)
155
+ break;
156
+ }
157
+ }
158
+ }
159
+ catch {
160
+ continue;
161
+ }
162
+ }
163
+ return matches;
164
+ }
165
+ export function getGitStatusSummary(rootDir) {
166
+ const branch = runGit(rootDir, ['branch', '--show-current']);
167
+ const status = runGit(rootDir, ['status', '--short']);
168
+ if (!status.ok) {
169
+ return `ERRO: git status falhou: ${(status.stderr || status.stdout || 'repo sem git?').trim()}`;
170
+ }
171
+ const changed = status.stdout.split(/\r?\n/).filter(Boolean);
172
+ return [
173
+ `branch: ${branch.ok && branch.stdout.trim() ? branch.stdout.trim() : '(sem branch)'}`,
174
+ `arquivos alterados: ${changed.length}`,
175
+ changed.length ? changed.join('\n') : '(worktree limpo)',
176
+ ].join('\n');
177
+ }
178
+ export function getGitDiff(rootDir) {
179
+ const diff = runGit(rootDir, ['diff', '--', '.']);
180
+ if (!diff.ok) {
181
+ return `ERRO: git diff falhou: ${(diff.stderr || diff.stdout || 'repo sem git?').trim()}`;
182
+ }
183
+ const redacted = redactSecrets(diff.stdout);
184
+ return clipToolOutput('git diff', redacted || '(sem diff)');
185
+ }
186
+ export function getProjectOverview(rootDir) {
187
+ const files = listFiles(rootDir);
188
+ const rows = [
189
+ `pasta: ${path.resolve(rootDir)}`,
190
+ `arquivos rastreados/listados: ${files.length}`,
191
+ ];
192
+ const packageJson = path.join(path.resolve(rootDir), 'package.json');
193
+ if (fs.existsSync(packageJson)) {
194
+ try {
195
+ const pkg = JSON.parse(fs.readFileSync(packageJson, 'utf8'));
196
+ if (typeof pkg.name === 'string')
197
+ rows.push(`package: ${pkg.name}`);
198
+ if (typeof pkg.version === 'string')
199
+ rows.push(`versao: ${pkg.version}`);
200
+ const scripts = pkg.scripts ? Object.keys(pkg.scripts).slice(0, 12) : [];
201
+ if (scripts.length)
202
+ rows.push(`scripts: ${scripts.join(', ')}`);
203
+ rows.push(`deps: ${pkg.dependencies ? Object.keys(pkg.dependencies).length : 0}`);
204
+ rows.push(`devDeps: ${pkg.devDependencies ? Object.keys(pkg.devDependencies).length : 0}`);
205
+ }
206
+ catch (error) {
207
+ rows.push(`package.json: erro ao ler (${error instanceof Error ? error.message : String(error)})`);
208
+ }
209
+ }
210
+ rows.push('');
211
+ rows.push('arquivos principais:');
212
+ rows.push(...files.slice(0, 80));
213
+ if (files.length > 80)
214
+ rows.push(`... mais ${files.length - 80} arquivo(s)`);
215
+ return rows.join('\n');
216
+ }
217
+ /**
218
+ * Le varios arquivos numa so chamada (Fase 3) — bounded pra nao estourar o
219
+ * contexto do gateway numa unica tool call. Reusa readFileContext (mesma
220
+ * contencao de path/symlink + bloqueio de segredo + truncamento por arquivo).
221
+ * Um path invalido nao aborta os demais — devolve a mensagem de erro inline
222
+ * no lugar do conteudo, como o resto das tools.
223
+ */
224
+ export function readManyFiles(rootDir, paths) {
225
+ const bounded = paths.slice(0, MAX_READ_MANY_FILES);
226
+ const blocks = bounded.map((p) => {
227
+ try {
228
+ return readFileContext(rootDir, p);
229
+ }
230
+ catch (error) {
231
+ return `--- ${p} ---\nERRO: ${error instanceof Error ? error.message : String(error)}`;
232
+ }
233
+ });
234
+ if (paths.length > MAX_READ_MANY_FILES) {
235
+ blocks.push(`[TRUNCADO: pedidos ${paths.length}, lidos ${MAX_READ_MANY_FILES}]`);
236
+ }
237
+ return clipToolOutput('read_many_files', blocks.join('\n\n'));
238
+ }
239
+ /**
240
+ * Busca por regex (Fase 3) — mesma varredura arquivo-a-arquivo de searchFiles,
241
+ * mas casando `pattern` como expressao regular em vez de substring literal.
242
+ *
243
+ * Mitigacao ReDoS (defense-in-depth, nao prova formal): pattern vem do
244
+ * modelo, entao (1) limita tamanho do pattern, (2) testa linha-a-linha (nao
245
+ * o arquivo inteiro) e pula linhas absurdamente longas, (3) constroi UM
246
+ * RegExp por chamada (nao por linha) mas sempre sem estado global preso
247
+ * entre chamadas (`String.prototype.match`, nao `exec` com `g` reaproveitado).
248
+ */
249
+ export function searchFilesRegex(rootDir, pattern, flags = '') {
250
+ if (!pattern)
251
+ return [];
252
+ if (pattern.length > MAX_REGEX_PATTERN_CHARS) {
253
+ throw new Error(`Pattern regex maior que ${MAX_REGEX_PATTERN_CHARS} chars.`);
254
+ }
255
+ const safeFlags = Array.from(new Set(flags.split(''))).filter((f) => 'imsu'.includes(f)).join('');
256
+ let regex;
257
+ try {
258
+ regex = new RegExp(pattern, safeFlags);
259
+ }
260
+ catch (error) {
261
+ throw new Error(`Regex invalida: ${error instanceof Error ? error.message : String(error)}`);
262
+ }
263
+ const matches = [];
264
+ for (const file of listFiles(rootDir)) {
265
+ if (matches.length >= MAX_SEARCH_MATCHES)
266
+ break;
267
+ if (isSecretPath(file))
268
+ continue;
269
+ try {
270
+ const full = resolveInside(rootDir, file);
271
+ const stat = fs.statSync(full);
272
+ if (!stat.isFile() || stat.size > MAX_FILE_BYTES)
273
+ continue;
274
+ const lines = redactSecrets(fs.readFileSync(full, 'utf8')).split(/\r?\n/);
275
+ for (let i = 0; i < lines.length; i++) {
276
+ if (lines[i].length > MAX_REGEX_LINE_CHARS)
277
+ continue;
278
+ if (regex.test(lines[i])) {
279
+ matches.push(`${file}:${i + 1}: ${lines[i].slice(0, 240)}`);
280
+ if (matches.length >= MAX_SEARCH_MATCHES)
281
+ break;
282
+ }
283
+ }
284
+ }
285
+ catch {
286
+ continue;
287
+ }
288
+ }
289
+ return matches;
290
+ }
291
+ /**
292
+ * Roda o script `test` do package.json (Fase 3) — SEM aceitar comando livre
293
+ * do modelo. O modelo so pode disparar exatamente o script ja configurado
294
+ * pelo dev no projeto (allowlist = "so o que ja existe em package.json.scripts
295
+ * .test"); isso fecha a porta pra um "run_tests" virar backdoor de execucao
296
+ * arbitraria de comando via prompt injection.
297
+ */
298
+ export function runProjectTests(rootDir) {
299
+ const pkgPath = path.join(path.resolve(rootDir), 'package.json');
300
+ if (!fs.existsSync(pkgPath)) {
301
+ return 'ERRO: package.json nao encontrado — sem script de teste configurado.';
302
+ }
303
+ let scripts = {};
304
+ try {
305
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
306
+ scripts = pkg.scripts ?? {};
307
+ }
308
+ catch (error) {
309
+ return `ERRO: package.json invalido: ${error instanceof Error ? error.message : String(error)}`;
310
+ }
311
+ if (typeof scripts.test !== 'string' || !scripts.test.trim()) {
312
+ return 'ERRO: package.json nao tem script "test" configurado.';
313
+ }
314
+ const result = spawnSync('npm', ['test', '--silent'], {
315
+ cwd: rootDir,
316
+ encoding: 'utf8',
317
+ timeout: RUN_TESTS_TIMEOUT_MS,
318
+ // Windows resolve `npm` como `npm.cmd` — spawnSync sem shell falha (ENOENT
319
+ // silencioso, status null) sem isso. Mesmo padrao de build.ts/bootstrap.ts.
320
+ shell: process.platform === 'win32',
321
+ });
322
+ const output = [result.stdout, result.stderr].filter(Boolean).join('\n');
323
+ const redacted = redactSecrets(output);
324
+ const status = result.status === 0 ? 'PASSOU' : `FALHOU (exit ${result.status ?? 'timeout'})`;
325
+ return clipToolOutput('run_tests', `status: ${status}\n\n${redacted || '(sem saida)'}`);
326
+ }
327
+ const SYMBOL_PATTERN = /^\s*export\s+(?:default\s+)?(?:async\s+)?(function\*?|class|const|let|interface|type|enum)\s+([A-Za-z_$][\w$]*)/;
328
+ /**
329
+ * Outline leve de simbolos exportados (Fase 3) — sem language server: regex
330
+ * sobre `export function/class/const/interface/type/enum` no topo do
331
+ * arquivo. Suficiente pra IA se orientar sem ler o arquivo inteiro; nao
332
+ * substitui `read_file` quando precisar do corpo real.
333
+ */
334
+ export function projectSymbols(rootDir, targetPath) {
335
+ const files = targetPath ? [targetPath] : listFiles(rootDir).filter((f) => /\.(ts|tsx|js|jsx)$/.test(f));
336
+ const bounded = files.slice(0, MAX_SYMBOL_FILES);
337
+ const rows = [];
338
+ for (const file of bounded) {
339
+ if (rows.length >= MAX_SYMBOLS)
340
+ break;
341
+ if (isSecretPath(file))
342
+ continue;
343
+ try {
344
+ const full = resolveInside(rootDir, file);
345
+ const stat = fs.statSync(full);
346
+ if (!stat.isFile() || stat.size > MAX_FILE_BYTES)
347
+ continue;
348
+ const lines = fs.readFileSync(full, 'utf8').split(/\r?\n/);
349
+ for (let i = 0; i < lines.length; i++) {
350
+ const match = SYMBOL_PATTERN.exec(lines[i]);
351
+ if (match) {
352
+ rows.push(`${file}:${i + 1}: ${match[1]} ${match[2]}`);
353
+ if (rows.length >= MAX_SYMBOLS)
354
+ break;
355
+ }
356
+ }
357
+ }
358
+ catch {
359
+ continue;
360
+ }
361
+ }
362
+ if (rows.length === 0)
363
+ return '(nenhum simbolo exportado encontrado)';
364
+ if (files.length > bounded.length)
365
+ rows.push(`[TRUNCADO: ${files.length} arquivo(s) elegiveis, ${bounded.length} varridos]`);
366
+ return rows.join('\n');
367
+ }
368
+ export function runCodeTool(rootDir, request) {
369
+ try {
370
+ if (request.tool === 'read_file') {
371
+ if (typeof request.path !== 'string' || !request.path.trim()) {
372
+ return 'ERRO: read_file exige path string.';
373
+ }
374
+ return readFileContext(rootDir, request.path);
375
+ }
376
+ if (request.tool === 'list_files') {
377
+ const pattern = typeof request.pattern === 'string' ? request.pattern : '';
378
+ return listFiles(rootDir, pattern).join('\n') || '(nenhum arquivo encontrado)';
379
+ }
380
+ if (request.tool === 'search') {
381
+ if (typeof request.query !== 'string' || !request.query) {
382
+ return 'ERRO: search exige query string.';
383
+ }
384
+ return searchFiles(rootDir, request.query).join('\n') || '(nenhuma ocorrencia encontrada)';
385
+ }
386
+ if (request.tool === 'git_status') {
387
+ return getGitStatusSummary(rootDir);
388
+ }
389
+ if (request.tool === 'git_diff') {
390
+ return getGitDiff(rootDir);
391
+ }
392
+ if (request.tool === 'project_overview') {
393
+ return getProjectOverview(rootDir);
394
+ }
395
+ if (request.tool === 'read_many_files') {
396
+ const paths = Array.isArray(request.paths)
397
+ ? request.paths.filter((p) => typeof p === 'string' && !!p.trim())
398
+ : [];
399
+ if (paths.length === 0)
400
+ return 'ERRO: read_many_files exige paths: string[] nao vazio.';
401
+ return readManyFiles(rootDir, paths);
402
+ }
403
+ if (request.tool === 'search_regex') {
404
+ if (typeof request.pattern !== 'string' || !request.pattern) {
405
+ return 'ERRO: search_regex exige pattern string.';
406
+ }
407
+ const flags = typeof request.flags === 'string' ? request.flags : '';
408
+ return searchFilesRegex(rootDir, request.pattern, flags).join('\n') || '(nenhuma ocorrencia encontrada)';
409
+ }
410
+ if (request.tool === 'run_tests') {
411
+ return runProjectTests(rootDir);
412
+ }
413
+ if (request.tool === 'project_symbols') {
414
+ const targetPath = typeof request.path === 'string' && request.path.trim() ? request.path : undefined;
415
+ return projectSymbols(rootDir, targetPath);
416
+ }
417
+ if (request.tool === 'invalid')
418
+ return `ERRO: ${request.error ?? 'tool invalida'}`;
419
+ return `ERRO: tool desconhecida: ${request.tool}`;
420
+ }
421
+ catch (error) {
422
+ return `ERRO: ${error instanceof Error ? error.message : String(error)}`;
423
+ }
424
+ }
425
+ const ANSI_GREEN = '\x1B[32m';
426
+ const ANSI_RED = '\x1B[31m';
427
+ const ANSI_CYAN = '\x1B[36m';
428
+ const ANSI_DIM = '\x1B[2m';
429
+ const ANSI_RESET = '\x1B[0m';
430
+ function colorDiffLine(line) {
431
+ if (line.startsWith('+++') || line.startsWith('---'))
432
+ return `${ANSI_DIM}${line}${ANSI_RESET}`;
433
+ if (line.startsWith('+'))
434
+ return `${ANSI_GREEN}${line}${ANSI_RESET}`;
435
+ if (line.startsWith('-'))
436
+ return `${ANSI_RED}${line}${ANSI_RESET}`;
437
+ if (line.startsWith('@@'))
438
+ return `${ANSI_CYAN}${line}${ANSI_RESET}`;
439
+ if (line.startsWith('diff --git') || line.startsWith('index '))
440
+ return `${ANSI_DIM}${line}${ANSI_RESET}`;
441
+ return line;
442
+ }
443
+ /** Colore um unified diff linha a linha: `+` verde, `-` vermelho, `@@`/headers dim/cyan. */
444
+ export function renderColoredDiff(patch) {
445
+ return patch
446
+ .split('\n')
447
+ .map(colorDiffLine)
448
+ .join('\n');
449
+ }
450
+ export function applyUnifiedPatch(rootDir, patch) {
451
+ const check = spawnSync('git', ['apply', '--check', '-'], {
452
+ cwd: rootDir,
453
+ input: patch,
454
+ encoding: 'utf8',
455
+ });
456
+ if (check.status !== 0) {
457
+ throw new Error((check.stderr || check.stdout || 'git apply --check falhou').trim());
458
+ }
459
+ const apply = spawnSync('git', ['apply', '-'], {
460
+ cwd: rootDir,
461
+ input: patch,
462
+ encoding: 'utf8',
463
+ });
464
+ if (apply.status !== 0) {
465
+ throw new Error((apply.stderr || apply.stdout || 'git apply falhou').trim());
466
+ }
467
+ }
468
+ //# sourceMappingURL=code-agent-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-agent-files.js","sourceRoot":"","sources":["../../src/lib/code-agent-files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { CodeMessage, CodeSettings } from './code-agent-types.js';
2
+ export declare const AI_GATEWAY_CHAT_PATH = "/api/cli/v1/ai/chat";
3
+ export interface GatewayChatResponse {
4
+ choices?: Array<{
5
+ message?: {
6
+ role?: CodeMessage['role'];
7
+ content?: string;
8
+ };
9
+ }>;
10
+ model?: string;
11
+ provider?: string;
12
+ }
13
+ export declare function callGateway(settings: CodeSettings, messages: CodeMessage[]): Promise<string>;
14
+ /**
15
+ * Chamada com streaming (Fase 5, NEETRU_CODE_ARCHITECTURE.md: "streaming de
16
+ * resposta se o AI Gateway suportar"). Mesmo padrão de `streamGateway` em
17
+ * `src/lib/ai/orchestrator.ts` (fetch direto + `readSseLines` compartilhado) —
18
+ * não passa por `apiRequest`/`apiStream` porque nenhum dos dois fala SSE, e
19
+ * não importa o orchestrator inteiro só por essa função (ele carrega
20
+ * @anthropic-ai/sdk + openai, que `neetru code` não precisa).
21
+ *
22
+ * Acumula os deltas e retorna o texto completo — o protocolo
23
+ * `NEETRU_TOOL`/`NEETRU_PATCH` só pode ser parseado sobre a resposta inteira,
24
+ * então `onDelta` serve só para feedback visual (ex: contador de chars
25
+ * recebidos), não para processar a resposta aos poucos.
26
+ */
27
+ export declare function streamGatewayChat(settings: CodeSettings, messages: CodeMessage[], onDelta?: (delta: string, totalChars: number) => void): Promise<string>;
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Chamada ao AI Gateway do Core pro `neetru code` — extraído de
3
+ * commands/code.ts (Fase 2, NEETRU_CODE_ARCHITECTURE.md: "separar núcleo de
4
+ * interface"). Sem lógica de UI/REPL — só monta e envia a requisição.
5
+ */
6
+ import { apiRequest, maybeWarnUntrustedHost } from './api-client.js';
7
+ import { getActiveTokenSync } from './token-resolver.js';
8
+ import { config } from './config.js';
9
+ import { readSseLines } from './sse.js';
10
+ export const AI_GATEWAY_CHAT_PATH = '/api/cli/v1/ai/chat';
11
+ export async function callGateway(settings, messages) {
12
+ const response = await apiRequest(AI_GATEWAY_CHAT_PATH, {
13
+ method: 'POST',
14
+ body: {
15
+ model: settings.model,
16
+ messages,
17
+ stream: false,
18
+ maxTokens: settings.maxTokens,
19
+ temperature: settings.temperature,
20
+ },
21
+ timeoutMs: settings.timeoutMs,
22
+ });
23
+ const content = response.choices?.[0]?.message?.content;
24
+ if (typeof content !== 'string') {
25
+ throw new Error('AI Gateway retornou resposta sem choices[0].message.content.');
26
+ }
27
+ return content;
28
+ }
29
+ /**
30
+ * Chamada com streaming (Fase 5, NEETRU_CODE_ARCHITECTURE.md: "streaming de
31
+ * resposta se o AI Gateway suportar"). Mesmo padrão de `streamGateway` em
32
+ * `src/lib/ai/orchestrator.ts` (fetch direto + `readSseLines` compartilhado) —
33
+ * não passa por `apiRequest`/`apiStream` porque nenhum dos dois fala SSE, e
34
+ * não importa o orchestrator inteiro só por essa função (ele carrega
35
+ * @anthropic-ai/sdk + openai, que `neetru code` não precisa).
36
+ *
37
+ * Acumula os deltas e retorna o texto completo — o protocolo
38
+ * `NEETRU_TOOL`/`NEETRU_PATCH` só pode ser parseado sobre a resposta inteira,
39
+ * então `onDelta` serve só para feedback visual (ex: contador de chars
40
+ * recebidos), não para processar a resposta aos poucos.
41
+ */
42
+ export async function streamGatewayChat(settings, messages, onDelta) {
43
+ const token = getActiveTokenSync();
44
+ if (!token) {
45
+ throw new Error('Sessao Neetru ausente ou expirada. Rode `neetru login`.');
46
+ }
47
+ const baseUrl = (config.get('neetruApiUrl') ?? 'https://api.neetru.com').replace(/\/+$/, '');
48
+ maybeWarnUntrustedHost(baseUrl);
49
+ const url = `${baseUrl}${AI_GATEWAY_CHAT_PATH}`;
50
+ const ctrl = new AbortController();
51
+ const timer = setTimeout(() => ctrl.abort(new Error(`neetru code stream timeout (${settings.timeoutMs}ms)`)), settings.timeoutMs);
52
+ try {
53
+ let resp;
54
+ try {
55
+ resp = await fetch(url, {
56
+ method: 'POST',
57
+ headers: {
58
+ 'content-type': 'application/json',
59
+ accept: 'text/event-stream',
60
+ authorization: `Bearer ${token}`,
61
+ },
62
+ body: JSON.stringify({
63
+ model: settings.model,
64
+ messages,
65
+ stream: true,
66
+ maxTokens: settings.maxTokens,
67
+ temperature: settings.temperature,
68
+ }),
69
+ signal: ctrl.signal,
70
+ });
71
+ }
72
+ catch (error) {
73
+ if (ctrl.signal.aborted)
74
+ throw error;
75
+ throw new Error(`Falha ao contactar o AI Gateway (${url}): ${error?.message ?? String(error)}`);
76
+ }
77
+ if (!resp.ok) {
78
+ const bodyText = await resp.text().catch(() => '');
79
+ let detail = bodyText;
80
+ try {
81
+ const parsed = JSON.parse(bodyText);
82
+ if (parsed?.error?.message)
83
+ detail = parsed.error.message;
84
+ }
85
+ catch {
86
+ // corpo nao-JSON — usa o texto cru (truncado abaixo).
87
+ }
88
+ throw new Error(`AI Gateway retornou ${resp.status}: ${detail.slice(0, 300) || 'erro sem detalhe'}`);
89
+ }
90
+ if (!resp.body)
91
+ throw new Error('AI Gateway retornou resposta sem body.');
92
+ let content = '';
93
+ await readSseLines(resp.body, (payload) => {
94
+ if (payload === '[DONE]')
95
+ return;
96
+ let obj;
97
+ try {
98
+ obj = JSON.parse(payload);
99
+ }
100
+ catch {
101
+ return; // linha nao-JSON (keep-alive) — ignora.
102
+ }
103
+ const delta = obj?.choices?.[0]?.delta?.content;
104
+ if (typeof delta === 'string' && delta) {
105
+ content += delta;
106
+ onDelta?.(delta, content.length);
107
+ }
108
+ });
109
+ return content;
110
+ }
111
+ finally {
112
+ clearTimeout(timer);
113
+ }
114
+ }
115
+ //# sourceMappingURL=code-agent-gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-agent-gateway.js","sourceRoot":"","sources":["../../src/lib/code-agent-gateway.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGxC,MAAM,CAAC,MAAM,oBAAoB,GAAG,qBAAqB,CAAC;AAa1D,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAsB,EAAE,QAAuB;IAC/E,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAsB,oBAAoB,EAAE;QAC3E,MAAM,EAAE,MAAM;QACd,IAAI,EAAE;YACJ,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,QAAQ;YACR,MAAM,EAAE,KAAK;YACb,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,WAAW,EAAE,QAAQ,CAAC,WAAW;SAClC;QACD,SAAS,EAAE,QAAQ,CAAC,SAAS;KAC9B,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC;IACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAsB,EACtB,QAAuB,EACvB,OAAqD;IAErD,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,wBAAwB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC7F,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAChC,MAAM,GAAG,GAAG,GAAG,OAAO,GAAG,oBAAoB,EAAE,CAAC;IAEhD,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,UAAU,CACtB,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,+BAA+B,QAAQ,CAAC,SAAS,KAAK,CAAC,CAAC,EACnF,QAAQ,CAAC,SAAS,CACnB,CAAC;IAEF,IAAI,CAAC;QACH,IAAI,IAAc,CAAC;QACnB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBACtB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,MAAM,EAAE,mBAAmB;oBAC3B,aAAa,EAAE,UAAU,KAAK,EAAE;iBACjC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,QAAQ;oBACR,MAAM,EAAE,IAAI;oBACZ,SAAS,EAAE,QAAQ,CAAC,SAAS;oBAC7B,WAAW,EAAE,QAAQ,CAAC,WAAW;iBAClC,CAAC;gBACF,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO;gBAAE,MAAM,KAAK,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,oCAAoC,GAAG,MAAM,KAAK,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClG,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YACnD,IAAI,MAAM,GAAG,QAAQ,CAAC;YACtB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAoD,CAAC;gBACvF,IAAI,MAAM,EAAE,KAAK,EAAE,OAAO;oBAAE,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;YAC5D,CAAC;YAAC,MAAM,CAAC;gBACP,sDAAsD;YACxD,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,kBAAkB,EAAE,CAAC,CAAC;QACvG,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAE1E,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;YACxC,IAAI,OAAO,KAAK,QAAQ;gBAAE,OAAO;YACjC,IAAI,GAA0D,CAAC;YAC/D,IAAI,CAAC;gBACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,CAAC,wCAAwC;YAClD,CAAC;YACD,MAAM,KAAK,GAAG,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC;YAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,EAAE,CAAC;gBACvC,OAAO,IAAI,KAAK,CAAC;gBACjB,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YACnC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;IACjB,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC"}