@neetru/cli 2.14.0 → 2.16.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 (39) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/commands/build.d.ts +14 -0
  3. package/dist/commands/build.js +26 -2
  4. package/dist/commands/build.js.map +1 -1
  5. package/dist/commands/code.d.ts +10 -31
  6. package/dist/commands/code.js +269 -220
  7. package/dist/commands/code.js.map +1 -1
  8. package/dist/commands/servers.js +8 -7
  9. package/dist/commands/servers.js.map +1 -1
  10. package/dist/lib/agent-commands.d.ts +16 -7
  11. package/dist/lib/agent-commands.js +40 -26
  12. package/dist/lib/agent-commands.js.map +1 -1
  13. package/dist/lib/ai/orchestrator.js +1 -42
  14. package/dist/lib/ai/orchestrator.js.map +1 -1
  15. package/dist/lib/code-agent-files.d.ts +48 -0
  16. package/dist/lib/code-agent-files.js +285 -2
  17. package/dist/lib/code-agent-files.js.map +1 -1
  18. package/dist/lib/code-agent-gateway.d.ts +27 -0
  19. package/dist/lib/code-agent-gateway.js +115 -0
  20. package/dist/lib/code-agent-gateway.js.map +1 -0
  21. package/dist/lib/code-agent-protocol.d.ts +8 -0
  22. package/dist/lib/code-agent-protocol.js +22 -0
  23. package/dist/lib/code-agent-protocol.js.map +1 -1
  24. package/dist/lib/code-agent-session.d.ts +78 -0
  25. package/dist/lib/code-agent-session.js +188 -0
  26. package/dist/lib/code-agent-session.js.map +1 -0
  27. package/dist/lib/code-agent-tools.d.ts +17 -0
  28. package/dist/lib/code-agent-tools.js +52 -0
  29. package/dist/lib/code-agent-tools.js.map +1 -0
  30. package/dist/lib/code-agent-types.d.ts +34 -0
  31. package/dist/lib/code-agent-types.js +7 -0
  32. package/dist/lib/code-agent-types.js.map +1 -0
  33. package/dist/lib/code-agent-ui.d.ts +49 -0
  34. package/dist/lib/code-agent-ui.js +313 -0
  35. package/dist/lib/code-agent-ui.js.map +1 -0
  36. package/dist/lib/sse.d.ts +14 -0
  37. package/dist/lib/sse.js +43 -0
  38. package/dist/lib/sse.js.map +1 -0
  39. package/package.json +1 -1
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Orçamento de payload TOTAL do histórico antes de disparar auto-compact
3
+ * (GAP-M1-15). 3x o limite por mensagem — margem suficiente pra várias
4
+ * tool results grandes coexistirem sem se aproximar do teto de payload
5
+ * observado no provider (HTTP 413), sem compactar cedo demais em sessões
6
+ * normais (poucos turnos, resultados pequenos).
7
+ */
8
+ export declare const MAX_HISTORY_TOTAL_CHARS: number;
9
+ /**
10
+ * Máquina de estados da sessão do `neetru code` (Fase 2,
11
+ * NEETRU_CODE_ARCHITECTURE.md: "Estados da sessão" — "hoje isso esta
12
+ * implicito por prints; o proximo passo e transformar em estrutura
13
+ * testavel"). Pura, sem I/O — commands/code.ts chama `transition()` nos
14
+ * pontos do loop de turno; testes verificam a sequência sem mockar o
15
+ * AI Gateway inteiro.
16
+ */
17
+ export type CodeAgentState = 'idle' | 'thinking' | 'tool_requested' | 'tool_running' | 'patch_ready' | 'awaiting_confirm' | 'applied' | 'failed' | 'aborted';
18
+ export declare class CodeAgentStateMachine {
19
+ private current;
20
+ private readonly log;
21
+ get state(): CodeAgentState;
22
+ /** Histórico de estados desde a criação (ou último `reset`). Só leitura. */
23
+ get history(): readonly CodeAgentState[];
24
+ transition(next: CodeAgentState): void;
25
+ reset(): void;
26
+ }
27
+ export type CodeSessionRole = 'system' | 'user' | 'assistant';
28
+ export interface CodeSessionMessage {
29
+ role: CodeSessionRole;
30
+ content: string;
31
+ }
32
+ export interface CodeSessionSnapshot {
33
+ cwd: string;
34
+ model: string;
35
+ }
36
+ export declare function compactCodeHistory<T extends CodeSessionMessage>(history: T[], keepRecent?: number): number;
37
+ /**
38
+ * GAP-M1-15 (2026-07-10): `compactCodeHistory` só rodava via `/compact`
39
+ * manual — numa sessao com varias tool calls (cada resultado pode chegar a
40
+ * MAX_GATEWAY_SAFE_CHARS ~28k), o payload TOTAL da requisicao (soma de todas
41
+ * as mensagens) cresce sem limite ate estourar HTTP 413 (Payload Too Large)
42
+ * no provider, mesmo com cada mensagem individual dentro do limite. Achado
43
+ * rodando `neetru code` de verdade: 4 turnos com tool results grandes
44
+ * bastaram pra estourar o Groq.
45
+ *
46
+ * Compacta por TAMANHO (soma de `content.length`), nao por contagem —
47
+ * remove as mensagens mais antigas (preservando sempre `system` e a
48
+ * ultima mensagem, que e o turno atual) ate caber no orcamento. Diferente
49
+ * de `compactCodeHistory` (contagem fixa), aqui uma unica tool result
50
+ * gigante ja pode disparar a compactacao mesmo com poucas mensagens.
51
+ */
52
+ export declare function compactHistoryToFit<T extends CodeSessionMessage>(history: T[], maxTotalChars: number): number;
53
+ export declare function formatCodeSessionMarkdown(settings: CodeSessionSnapshot, history: CodeSessionMessage[]): string;
54
+ export declare function saveCodeSession(settings: CodeSessionSnapshot, history: CodeSessionMessage[]): string;
55
+ /**
56
+ * Retomar sessao por id (Fase 4, NEETRU_CODE_ARCHITECTURE.md) — mesmo padrao
57
+ * de UX de qualquer REPL com persistencia (lista sessoes salvas, numera,
58
+ * usuario escolhe). Nada disso vem de codigo alheio: e o jeito obvio de
59
+ * resolver "listar + escolher" numa CLI de terminal.
60
+ */
61
+ export interface CodeSessionSummary {
62
+ /** Path relativo ao cwd (ex: `.neetru/code/sessions/2026-07-10T...-abc.md`). */
63
+ file: string;
64
+ timestamp: string;
65
+ messageCount: number;
66
+ /** Primeiras ~80 chars da primeira mensagem de usuario — ajuda a reconhecer a sessao na lista. */
67
+ preview: string;
68
+ }
69
+ /** Lista sessoes salvas, mais recente primeiro (nomes de arquivo ISO ordenam lexicograficamente). */
70
+ export declare function listCodeSessions(cwd: string): CodeSessionSummary[];
71
+ /** Carrega as mensagens de uma sessao salva (`file` relativo ao cwd, vindo de listCodeSessions). */
72
+ export declare function loadCodeSession(cwd: string, file: string): CodeSessionMessage[];
73
+ /**
74
+ * Log local de patch aplicado (Fase 4) — 1 linha por patch, append-only.
75
+ * Nao substitui git log/reflog; e so um resumo rapido "o que o agente mudou
76
+ * e quando", legivel sem abrir o git.
77
+ */
78
+ export declare function logAppliedPatch(cwd: string, summary: string): void;
@@ -0,0 +1,188 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { redactSecrets, MAX_GATEWAY_SAFE_CHARS } from './code-agent-files.js';
4
+ /**
5
+ * Orçamento de payload TOTAL do histórico antes de disparar auto-compact
6
+ * (GAP-M1-15). 3x o limite por mensagem — margem suficiente pra várias
7
+ * tool results grandes coexistirem sem se aproximar do teto de payload
8
+ * observado no provider (HTTP 413), sem compactar cedo demais em sessões
9
+ * normais (poucos turnos, resultados pequenos).
10
+ */
11
+ export const MAX_HISTORY_TOTAL_CHARS = MAX_GATEWAY_SAFE_CHARS * 3;
12
+ const VALID_TRANSITIONS = {
13
+ idle: ['thinking'],
14
+ // thinking -> idle: turno terminou em texto final (sem tool nem patch).
15
+ thinking: ['tool_requested', 'patch_ready', 'idle', 'failed'],
16
+ tool_requested: ['tool_running'],
17
+ tool_running: ['thinking', 'failed'],
18
+ patch_ready: ['awaiting_confirm', 'applied', 'aborted'],
19
+ awaiting_confirm: ['applied', 'aborted'],
20
+ applied: ['idle'],
21
+ failed: ['idle'],
22
+ aborted: ['idle'],
23
+ };
24
+ export class CodeAgentStateMachine {
25
+ current = 'idle';
26
+ log = ['idle'];
27
+ get state() {
28
+ return this.current;
29
+ }
30
+ /** Histórico de estados desde a criação (ou último `reset`). Só leitura. */
31
+ get history() {
32
+ return this.log;
33
+ }
34
+ transition(next) {
35
+ const allowed = VALID_TRANSITIONS[this.current];
36
+ if (!allowed.includes(next)) {
37
+ throw new Error(`Transicao de estado invalida: ${this.current} -> ${next}`);
38
+ }
39
+ this.current = next;
40
+ this.log.push(next);
41
+ }
42
+ reset() {
43
+ this.current = 'idle';
44
+ this.log.length = 0;
45
+ this.log.push('idle');
46
+ }
47
+ }
48
+ export function compactCodeHistory(history, keepRecent = 8) {
49
+ if (history.length <= keepRecent + 1)
50
+ return 0;
51
+ const system = history.find((message) => message.role === 'system');
52
+ const recent = history.slice(-keepRecent);
53
+ const next = system ? [system, ...recent.filter((message) => message !== system)] : recent;
54
+ const removed = history.length - next.length;
55
+ history.splice(0, history.length, ...next);
56
+ return removed;
57
+ }
58
+ /**
59
+ * GAP-M1-15 (2026-07-10): `compactCodeHistory` só rodava via `/compact`
60
+ * manual — numa sessao com varias tool calls (cada resultado pode chegar a
61
+ * MAX_GATEWAY_SAFE_CHARS ~28k), o payload TOTAL da requisicao (soma de todas
62
+ * as mensagens) cresce sem limite ate estourar HTTP 413 (Payload Too Large)
63
+ * no provider, mesmo com cada mensagem individual dentro do limite. Achado
64
+ * rodando `neetru code` de verdade: 4 turnos com tool results grandes
65
+ * bastaram pra estourar o Groq.
66
+ *
67
+ * Compacta por TAMANHO (soma de `content.length`), nao por contagem —
68
+ * remove as mensagens mais antigas (preservando sempre `system` e a
69
+ * ultima mensagem, que e o turno atual) ate caber no orcamento. Diferente
70
+ * de `compactCodeHistory` (contagem fixa), aqui uma unica tool result
71
+ * gigante ja pode disparar a compactacao mesmo com poucas mensagens.
72
+ */
73
+ export function compactHistoryToFit(history, maxTotalChars) {
74
+ const totalChars = (msgs) => msgs.reduce((sum, m) => sum + m.content.length, 0);
75
+ if (totalChars(history) <= maxTotalChars || history.length <= 1)
76
+ return 0;
77
+ const systemIdx = history.findIndex((m) => m.role === 'system');
78
+ const system = systemIdx >= 0 ? history[systemIdx] : null;
79
+ const rest = history.filter((_, i) => i !== systemIdx);
80
+ // Remove do mais antigo pro mais recente, sempre preservando a ultima
81
+ // mensagem (o turno atual) — sem ela o modelo perderia a propria pergunta.
82
+ while (rest.length > 1 && totalChars(system ? [system, ...rest] : rest) > maxTotalChars) {
83
+ rest.shift();
84
+ }
85
+ const next = system ? [system, ...rest] : rest;
86
+ const removed = history.length - next.length;
87
+ if (removed > 0)
88
+ history.splice(0, history.length, ...next);
89
+ return removed;
90
+ }
91
+ export function formatCodeSessionMarkdown(settings, history) {
92
+ const lines = [
93
+ '# Neetru Code Session',
94
+ '',
95
+ `- date: ${new Date().toISOString()}`,
96
+ `- cwd: ${settings.cwd}`,
97
+ `- model: ${settings.model}`,
98
+ `- messages: ${history.length}`,
99
+ '',
100
+ '## Conversa',
101
+ '',
102
+ ];
103
+ for (const message of history) {
104
+ lines.push(`### ${message.role}`);
105
+ lines.push('');
106
+ lines.push('```text');
107
+ lines.push(redactSecrets(message.content).slice(0, 40_000));
108
+ lines.push('```');
109
+ lines.push('');
110
+ }
111
+ return lines.join('\n');
112
+ }
113
+ export function saveCodeSession(settings, history) {
114
+ const dir = path.join(settings.cwd, '.neetru', 'code', 'sessions');
115
+ fs.mkdirSync(dir, { recursive: true });
116
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-');
117
+ const file = path.join(dir, `${stamp}.md`);
118
+ fs.writeFileSync(file, formatCodeSessionMarkdown(settings, history), 'utf8');
119
+ return path.relative(settings.cwd, file).replace(/\\/g, '/');
120
+ }
121
+ function sessionsDir(cwd) {
122
+ return path.join(cwd, '.neetru', 'code', 'sessions');
123
+ }
124
+ function parseSessionMarkdown(content) {
125
+ const dateMatch = content.match(/^- date: (.+)$/m);
126
+ const countMatch = content.match(/^- messages: (\d+)$/m);
127
+ const messages = [];
128
+ const blockRe = /### (system|user|assistant)\n\n```text\n([\s\S]*?)\n```/g;
129
+ let match;
130
+ while ((match = blockRe.exec(content))) {
131
+ messages.push({ role: match[1], content: match[2] });
132
+ }
133
+ return {
134
+ date: dateMatch?.[1] ?? '',
135
+ messageCount: countMatch ? Number.parseInt(countMatch[1], 10) : messages.length,
136
+ messages,
137
+ };
138
+ }
139
+ /** Lista sessoes salvas, mais recente primeiro (nomes de arquivo ISO ordenam lexicograficamente). */
140
+ export function listCodeSessions(cwd) {
141
+ const dir = sessionsDir(cwd);
142
+ if (!fs.existsSync(dir))
143
+ return [];
144
+ const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md')).sort().reverse();
145
+ return files.map((file) => {
146
+ const full = path.join(dir, file);
147
+ let content = '';
148
+ try {
149
+ content = fs.readFileSync(full, 'utf8');
150
+ }
151
+ catch {
152
+ content = '';
153
+ }
154
+ const parsed = parseSessionMarkdown(content);
155
+ const firstUser = parsed.messages.find((m) => m.role === 'user');
156
+ const preview = (firstUser?.content ?? '').replace(/\s+/g, ' ').trim().slice(0, 80);
157
+ return {
158
+ file: `.neetru/code/sessions/${file}`,
159
+ timestamp: parsed.date || file.replace(/\.md$/, ''),
160
+ messageCount: parsed.messageCount,
161
+ preview,
162
+ };
163
+ });
164
+ }
165
+ /** Carrega as mensagens de uma sessao salva (`file` relativo ao cwd, vindo de listCodeSessions). */
166
+ export function loadCodeSession(cwd, file) {
167
+ const full = path.resolve(cwd, file);
168
+ if (!full.startsWith(path.resolve(sessionsDir(cwd)))) {
169
+ throw new Error(`Sessao fora do diretorio esperado: ${file}`);
170
+ }
171
+ if (!fs.existsSync(full)) {
172
+ throw new Error(`Sessao nao encontrada: ${file}`);
173
+ }
174
+ const content = fs.readFileSync(full, 'utf8');
175
+ return parseSessionMarkdown(content).messages;
176
+ }
177
+ /**
178
+ * Log local de patch aplicado (Fase 4) — 1 linha por patch, append-only.
179
+ * Nao substitui git log/reflog; e so um resumo rapido "o que o agente mudou
180
+ * e quando", legivel sem abrir o git.
181
+ */
182
+ export function logAppliedPatch(cwd, summary) {
183
+ const dir = path.join(cwd, '.neetru', 'code');
184
+ fs.mkdirSync(dir, { recursive: true });
185
+ const file = path.join(dir, 'patches.log');
186
+ fs.appendFileSync(file, `${new Date().toISOString()} ${summary}\n`, 'utf8');
187
+ }
188
+ //# sourceMappingURL=code-agent-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-agent-session.js","sourceRoot":"","sources":["../../src/lib/code-agent-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Registro de ferramentas locais do `neetru code` — extraído de
3
+ * commands/code.ts (Fase 2, NEETRU_CODE_ARCHITECTURE.md: "separar núcleo de
4
+ * interface"). O system prompt é montado a partir do registro: Fase 3
5
+ * (run_tests, read_many_files, search_regex, project_symbols) só precisa
6
+ * adicionar entradas aqui — não editar o prompt à mão em vários lugares.
7
+ *
8
+ * Execução real das ferramentas (I/O de arquivo/git) mora em
9
+ * code-agent-files.ts — este módulo só descreve o protocolo pro modelo.
10
+ */
11
+ export interface CodeToolDescriptor {
12
+ name: string;
13
+ /** Linha de invocação mostrada no system prompt (protocolo NEETRU_TOOL). */
14
+ usage: string;
15
+ }
16
+ export declare const CODE_TOOL_REGISTRY: CodeToolDescriptor[];
17
+ export declare function buildSystemPrompt(): string;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Registro de ferramentas locais do `neetru code` — extraído de
3
+ * commands/code.ts (Fase 2, NEETRU_CODE_ARCHITECTURE.md: "separar núcleo de
4
+ * interface"). O system prompt é montado a partir do registro: Fase 3
5
+ * (run_tests, read_many_files, search_regex, project_symbols) só precisa
6
+ * adicionar entradas aqui — não editar o prompt à mão em vários lugares.
7
+ *
8
+ * Execução real das ferramentas (I/O de arquivo/git) mora em
9
+ * code-agent-files.ts — este módulo só descreve o protocolo pro modelo.
10
+ */
11
+ export const CODE_TOOL_REGISTRY = [
12
+ { name: 'read_file', usage: 'NEETRU_TOOL {"tool":"read_file","path":"caminho/relativo.ext"}' },
13
+ { name: 'list_files', usage: 'NEETRU_TOOL {"tool":"list_files","pattern":"texto opcional"}' },
14
+ { name: 'search', usage: 'NEETRU_TOOL {"tool":"search","query":"texto literal"}' },
15
+ { name: 'git_status', usage: 'NEETRU_TOOL {"tool":"git_status"}' },
16
+ { name: 'git_diff', usage: 'NEETRU_TOOL {"tool":"git_diff"}' },
17
+ { name: 'project_overview', usage: 'NEETRU_TOOL {"tool":"project_overview"}' },
18
+ // Fase 3 (NEETRU_CODE_ARCHITECTURE.md): ferramentas produtivas.
19
+ { name: 'read_many_files', usage: 'NEETRU_TOOL {"tool":"read_many_files","paths":["a.ts","b.ts"]}' },
20
+ { name: 'search_regex', usage: 'NEETRU_TOOL {"tool":"search_regex","pattern":"regex","flags":"i opcional"}' },
21
+ { name: 'run_tests', usage: 'NEETRU_TOOL {"tool":"run_tests"}' },
22
+ { name: 'project_symbols', usage: 'NEETRU_TOOL {"tool":"project_symbols","path":"opcional/um-arquivo.ts"}' },
23
+ ];
24
+ export function buildSystemPrompt() {
25
+ const toolLines = CODE_TOOL_REGISTRY.map((tool) => tool.usage).join('\n');
26
+ return `
27
+ Voce e o Neetru Code, um assistente local de codificacao da Neetru.
28
+ Voce conversa com modelos do AI Gateway do Neetru Core, normalmente Groq/NVIDIA.
29
+ Nao use Anthropic/Claude como caminho assumido.
30
+
31
+ Voce nao tem tool calling nativo. Use exatamente estes protocolos textuais:
32
+
33
+ ${toolLines}
34
+
35
+ Regras:
36
+ - Peca arquivos antes de alterar codigo quando faltar contexto.
37
+ - Use project_overview/git_status quando precisar entender o projeto antes de editar.
38
+ - Use git_diff antes de revisar mudancas ja existentes.
39
+ - Nunca invente conteudo de arquivo.
40
+ - Peca uma tool por resposta, no maximo.
41
+ - Quando estiver pronto para alterar, responda somente com um diff aplicavel por git:
42
+
43
+ NEETRU_PATCH
44
+ diff --git a/path b/path
45
+ ...
46
+ NEETRU_END
47
+
48
+ - Nao coloque explicacao dentro do bloco NEETRU_PATCH.
49
+ - Se a tarefa nao exigir alteracao, responda em texto curto.
50
+ `.trim();
51
+ }
52
+ //# sourceMappingURL=code-agent-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-agent-tools.js","sourceRoot":"","sources":["../../src/lib/code-agent-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,MAAM,CAAC,MAAM,kBAAkB,GAAyB;IACtD,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,gEAAgE,EAAE;IAC9F,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,8DAA8D,EAAE;IAC7F,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,uDAAuD,EAAE;IAClF,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,mCAAmC,EAAE;IAClE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,iCAAiC,EAAE;IAC9D,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,yCAAyC,EAAE;IAC9E,gEAAgE;IAChE,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,gEAAgE,EAAE;IACpG,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,4EAA4E,EAAE;IAC7G,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,kCAAkC,EAAE;IAChE,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,wEAAwE,EAAE;CAC7G,CAAC;AAEF,MAAM,UAAU,iBAAiB;IAC/B,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE1E,OAAO;;;;;;;EAOP,SAAS;;;;;;;;;;;;;;;;;CAiBV,CAAC,IAAI,EAAE,CAAC;AACT,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Tipos compartilhados entre os módulos do `neetru code`
3
+ * (code.ts, code-agent-ui.ts, code-agent-gateway.ts, code-agent-tools.ts,
4
+ * code-agent-session.ts) — evita import circular de tipo entre eles.
5
+ */
6
+ export type CodeRole = 'system' | 'user' | 'assistant';
7
+ export interface CodeMessage {
8
+ role: CodeRole;
9
+ content: string;
10
+ }
11
+ export interface CodeCommandOptions {
12
+ cwd?: string;
13
+ file?: string[];
14
+ model?: string;
15
+ maxTurns?: string | number;
16
+ maxTokens?: string | number;
17
+ temperature?: string | number;
18
+ plan?: boolean;
19
+ apply?: boolean;
20
+ yes?: boolean;
21
+ }
22
+ export interface CodeSettings {
23
+ cwd: string;
24
+ files: string[];
25
+ model: string;
26
+ modelWarning?: string;
27
+ maxTurns: number;
28
+ maxTokens: number;
29
+ temperature: number;
30
+ apply: boolean;
31
+ yes: boolean;
32
+ timeoutMs: number;
33
+ }
34
+ export type ConfirmFn = (question: string) => Promise<boolean>;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Tipos compartilhados entre os módulos do `neetru code`
3
+ * (code.ts, code-agent-ui.ts, code-agent-gateway.ts, code-agent-tools.ts,
4
+ * code-agent-session.ts) — evita import circular de tipo entre eles.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=code-agent-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-agent-types.js","sourceRoot":"","sources":["../../src/lib/code-agent-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,49 @@
1
+ import { type CodeToolRequest } from './code-agent-protocol.js';
2
+ import type { CodeMessage, CodeSettings } from './code-agent-types.js';
3
+ export declare function stripAnsi(text: string): string;
4
+ export declare function visibleLength(text: string): number;
5
+ export declare function padVisible(text: string, width: number): string;
6
+ export declare function terminalWidth(): number;
7
+ export declare function truncateMiddle(text: string, max: number): string;
8
+ export declare function wrapPlain(text: string, width: number): string[];
9
+ export declare function printBox(title: string, rows?: string[]): void;
10
+ export declare function printStatusBar(settings: CodeSettings, mode: 'interactive' | 'oneshot' | 'doctor'): void;
11
+ export declare function printDivider(label?: string): void;
12
+ export declare function printEvent(kind: 'wait' | 'tool' | 'ok' | 'warn' | 'error', title: string, detail?: string): void;
13
+ export interface TurnSpinner {
14
+ /** Atualiza o texto de detalhe (ex: "142 char(s) recebido(s)") na próxima animação. */
15
+ update(detail?: string): void;
16
+ /** Para o spinner e limpa a linha. */
17
+ stop(): void;
18
+ }
19
+ /**
20
+ * Spinner de turno — mostra progresso ao vivo (frame animado + cor rotativa +
21
+ * tempo decorrido MM:SS) enquanto o AI Gateway processa. Cobre TANTO o
22
+ * caminho de streaming quanto o fallback sem stream — antes o fallback ficava
23
+ * mudo até a resposta chegar ou o timeout estourar, sem nenhum feedback.
24
+ * Sem-op em saída não-TTY (pipe/CI/teste) — não faz sentido redesenhar linha.
25
+ */
26
+ export declare function startTurnSpinner(label: string): TurnSpinner;
27
+ export declare function summarizeToolResult(result: string): string;
28
+ /**
29
+ * Resposta final do assistente — sem caixa ASCII (a caixa fazia `truncateMiddle`
30
+ * cortar linhas de prosa no meio, feio e ilegível). Marcador colorido + word-wrap
31
+ * natural do terminal, padrão comum de CLIs de chat modernas.
32
+ */
33
+ export declare function printAssistantText(content: string): void;
34
+ export declare function patchSummaryRows(patch: string): string[];
35
+ export declare function printPatchPreview(patch: string): void;
36
+ export declare function renderHeader(settings: CodeSettings, mode?: 'interactive' | 'oneshot' | 'doctor'): void;
37
+ export declare function renderInteractiveHelp(): void;
38
+ export declare function renderSessionStatus(settings: CodeSettings, history?: CodeMessage[]): void;
39
+ export declare function renderPrompt(settings: CodeSettings): string;
40
+ export declare function printFileSample(files: string[], total: number): void;
41
+ /** Picker de arquivos (Fase 5) — lista numerada; `/pick` pede o(s) numero(s) ao usuario. */
42
+ export declare function printFilePicker(files: string[], total: number): void;
43
+ /** Lista sessoes salvas numeradas (Fase 4) — usuario escolhe pelo numero em `/resume`. */
44
+ export declare function printSessionList(sessions: Array<{
45
+ timestamp: string;
46
+ messageCount: number;
47
+ preview: string;
48
+ }>): void;
49
+ export declare function toolDetail(tool: CodeToolRequest | null): string;