primocode 9.3.0 → 9.3.1
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 +2 -2
- package/bin/primocode.js +29 -0
- package/lib/compatibilidade.js +89 -0
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# PrimoCode v9.
|
|
1
|
+
# PrimoCode v9.3.1
|
|
2
2
|
|
|
3
3
|
Agente de engenharia brasileiro para o terminal, no estilo Claude Code.
|
|
4
4
|
Cria arquivos de verdade, roda comandos, **controla o navegador e o desktop** —
|
|
@@ -9,7 +9,7 @@ OpenRouter, e cada apelido (`top`/`main`/`fast`) é uma **corrente**: se um mode
|
|
|
9
9
|
está no limite de pedidos, o próximo atende. Você não vê o erro, e não paga nada.
|
|
10
10
|
|
|
11
11
|
```
|
|
12
|
-
▐▛███▜▌ Primo Code v9.
|
|
12
|
+
▐▛███▜▌ Primo Code v9.3.1
|
|
13
13
|
▝▜█████▛▘ Bem-vindo de volta, Joel
|
|
14
14
|
▘▘ ▝▝ ~/primocode · /dir <pasta> muda
|
|
15
15
|
```
|
package/bin/primocode.js
CHANGED
|
@@ -35,6 +35,7 @@ const vozModo = require('../lib/voz');
|
|
|
35
35
|
const appLib = require('../lib/app');
|
|
36
36
|
const conta = require('../lib/conta');
|
|
37
37
|
const nuvem = require('../lib/nuvem');
|
|
38
|
+
const compat = require('../lib/compatibilidade');
|
|
38
39
|
|
|
39
40
|
// Rede de segurança de último recurso: sem isto, uma exceção fora de um
|
|
40
41
|
// try/catch (ex.: dentro de um callback de socket, como o parser de SSE) não
|
|
@@ -1942,6 +1943,33 @@ function shortPath(p) {
|
|
|
1942
1943
|
return full.startsWith(home + '/') ? '~' + full.slice(home.length) : full;
|
|
1943
1944
|
}
|
|
1944
1945
|
|
|
1946
|
+
/* O CLIENTE NOVO E O SERVIDOR VELHO.
|
|
1947
|
+
*
|
|
1948
|
+
* Quem declara ao modelo quais ferramentas existem é o servidor. Quando a
|
|
1949
|
+
* lista dele fica para trás, o que a pessoa vê é "a ferramenta não está
|
|
1950
|
+
* disponível" e tarefas que param no meio — duas frases que não apontam para
|
|
1951
|
+
* a causa. Uma linha no começo da sessão troca isso por algo acionável.
|
|
1952
|
+
*
|
|
1953
|
+
* Sem prender nada: a busca corre em paralelo e, se o servidor estiver
|
|
1954
|
+
* dormindo ou a rede fora, não se diz nada. Acusar o servidor porque a rede
|
|
1955
|
+
* caiu manda consertar o que não quebrou. */
|
|
1956
|
+
let jaConferiu = false;
|
|
1957
|
+
function conferirServidor() {
|
|
1958
|
+
if (jaConferiu) return;
|
|
1959
|
+
jaConferiu = true;
|
|
1960
|
+
const minimo = (pkg.primocode && pkg.primocode.servidorMinimo) || '';
|
|
1961
|
+
if (!minimo) return;
|
|
1962
|
+
const servidor = state.config.server;
|
|
1963
|
+
Promise.resolve()
|
|
1964
|
+
.then(() => api.getHealth(servidor, state.config.token))
|
|
1965
|
+
.then((saude) => {
|
|
1966
|
+
const r = compat.avaliar({ saude, minimo, servidor });
|
|
1967
|
+
const texto = compat.aviso(r, c);
|
|
1968
|
+
if (texto) console.log('\n' + texto + '\n');
|
|
1969
|
+
})
|
|
1970
|
+
.catch(() => {});
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1945
1973
|
async function main() {
|
|
1946
1974
|
cfg.ensureStructure();
|
|
1947
1975
|
|
|
@@ -2200,6 +2228,7 @@ async function main() {
|
|
|
2200
2228
|
while (adiantadas.length) queue.push(adiantadas.shift());
|
|
2201
2229
|
if (queue.length) drain();
|
|
2202
2230
|
else if (!closed) rl.prompt();
|
|
2231
|
+
conferirServidor();
|
|
2203
2232
|
});
|
|
2204
2233
|
}
|
|
2205
2234
|
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* compatibilidade.js — o cliente novo conversando com o servidor velho.
|
|
3
|
+
*
|
|
4
|
+
* ── O SINTOMA, E POR QUE ELE ENGANA ──────────────────────────────────────
|
|
5
|
+
* Quem declara ao modelo QUAIS ferramentas existem é o servidor. Uma que não
|
|
6
|
+
* está na lista dele não existe para o modelo, por mais que o cliente saiba
|
|
7
|
+
* executá-la. Quando as duas listas divergem, o que a pessoa vê não tem nada
|
|
8
|
+
* a ver com a causa:
|
|
9
|
+
*
|
|
10
|
+
* - "a ferramenta necessária não está disponível" — o modelo chamou um nome
|
|
11
|
+
* que o servidor velho ainda oferece e que o cliente novo já não atende;
|
|
12
|
+
* - "ele faz uma parte e para" — as chamadas falham, a dívida de falhas
|
|
13
|
+
* pendentes nunca zera, e a tarefa morre em "parei sem concluir".
|
|
14
|
+
*
|
|
15
|
+
* Nenhuma dessas frases aponta para "o servidor está desatualizado", que é a
|
|
16
|
+
* única coisa acionável. O usuário passa a tarde achando que a IA é ruim.
|
|
17
|
+
*
|
|
18
|
+
* ── POR QUE A VERSÃO, E NÃO A LISTA DE FERRAMENTAS ───────────────────────
|
|
19
|
+
* Comparar as duas listas seria mais direto, mas o /health não as publica, e
|
|
20
|
+
* pedir a lista inteira a cada início de sessão custa mais do que informa. A
|
|
21
|
+
* versão é o que o /health já diz, e é suficiente: o contrato entre os dois
|
|
22
|
+
* repositórios muda junto com ela.
|
|
23
|
+
*
|
|
24
|
+
* ── O AVISO É UMA VEZ, E NÃO SEGURA NADA ─────────────────────────────────
|
|
25
|
+
* Ele sai no começo da sessão e some. Não bloqueia: o servidor velho ainda
|
|
26
|
+
* serve conversa, código e shell — o que ele não serve é o Estúdio. Travar a
|
|
27
|
+
* sessão inteira por causa disso trocaria um problema por um pior.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
'use strict';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Compara "8.11.0" com "8.12.0". Devolve -1, 0 ou 1.
|
|
34
|
+
*
|
|
35
|
+
* Só os três números importam: um sufixo de pré-lançamento ("8.12.0-rc.1") é
|
|
36
|
+
* ignorado de propósito. Quem roda um rc sabe o que está fazendo, e tratá-lo
|
|
37
|
+
* como anterior ao 8.12.0 faria o aviso aparecer justamente para quem já
|
|
38
|
+
* está à frente.
|
|
39
|
+
*/
|
|
40
|
+
function compararVersao(a, b) {
|
|
41
|
+
const partes = (v) => String(v || '0').split('-')[0].split('.').map((n) => Number(n) || 0);
|
|
42
|
+
const x = partes(a);
|
|
43
|
+
const y = partes(b);
|
|
44
|
+
for (let i = 0; i < 3; i++) {
|
|
45
|
+
if ((x[i] || 0) > (y[i] || 0)) return 1;
|
|
46
|
+
if ((x[i] || 0) < (y[i] || 0)) return -1;
|
|
47
|
+
}
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* O servidor atende este cliente?
|
|
53
|
+
*
|
|
54
|
+
* `saude` é a resposta do /health. Sem ela — rede fora, servidor dormindo no
|
|
55
|
+
* plano grátis — a resposta é "não sei", nunca "está velho": acusar o
|
|
56
|
+
* servidor porque a rede caiu manda a pessoa consertar o que não quebrou.
|
|
57
|
+
*/
|
|
58
|
+
function avaliar({ saude, minimo, servidor }) {
|
|
59
|
+
const versao = saude && typeof saude.version === 'string' ? saude.version : '';
|
|
60
|
+
if (!versao) return { ok: true, sabido: false };
|
|
61
|
+
if (compararVersao(versao, minimo) >= 0) return { ok: true, sabido: true, versao };
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
ok: false,
|
|
65
|
+
sabido: true,
|
|
66
|
+
versao,
|
|
67
|
+
minimo,
|
|
68
|
+
titulo: `O servidor está na versão ${versao}, e este cliente precisa da ${minimo} ou maior.`,
|
|
69
|
+
detalhe: 'Enquanto ele não subir, o Estúdio (vídeo, slides, arte) e a transcrição de áudio '
|
|
70
|
+
+ 'não funcionam: o servidor antigo oferece ao modelo ferramentas que este cliente já não '
|
|
71
|
+
+ 'atende, e a tarefa morre no meio sem dizer por quê.',
|
|
72
|
+
comoResolver: servidor
|
|
73
|
+
? `Confira com: curl -s ${servidor.replace(/\/+$/, '')}/health`
|
|
74
|
+
: 'Confira a versão em /health do servidor configurado.',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** O aviso pronto para a tela, ou vazio quando não há o que avisar. */
|
|
79
|
+
function aviso(r, cores) {
|
|
80
|
+
if (!r || r.ok) return '';
|
|
81
|
+
const c = cores || { warn: (t) => t, dim: (t) => t };
|
|
82
|
+
return [
|
|
83
|
+
c.warn(' ' + r.titulo),
|
|
84
|
+
c.dim(' ' + r.detalhe),
|
|
85
|
+
c.dim(' ' + r.comoResolver),
|
|
86
|
+
].join('\n');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = { compararVersao, avaliar, aviso };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "primocode",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.1",
|
|
4
4
|
"description": "PrimoCode — agente de engenharia com IA e cursor próprio. Requer conta Conecta Primo AI (Premium ou Super). Cria arquivos, roda comandos, controla navegador e desktop: abre apps, clica em botões e ícones pelo nome, digita e usa atalhos.",
|
|
5
5
|
"main": "bin/primocode.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "node bin/primocode.js",
|
|
11
|
-
"test": "node test/tools.test.js && node test/ui.test.js && node test/entrada.test.js && node test/transparencia.test.js && node test/permissao.test.js && node test/skills.test.js && node test/estudio.test.js && node test/voz.test.js && node test/modo.test.js && node test/pasta.test.js && node test/catalogo.test.js && node test/desktop.test.js && node test/effort.test.js && node test/regressao.test.js && node test/memoria-conversa.test.js && node test/repeticao.test.js && node test/referencia.test.js && node test/parar.test.js && node test/continuar.test.js && node test/pipeline.test.js && node test/app.test.js && node test/aplicativo.test.js && node test/conta.test.mjs && node test/nuvem.test.js && node test/prazo.test.js && node test/primeira-vez.test.js && node test/janela.test.js && node test/pareamento.test.js && node test/fala.test.js && node test/especialistas.test.js && node test/empurrao.test.js && node test/terminal-novo.test.js && node test/markdown.test.js && node test/coerencia.test.js"
|
|
11
|
+
"test": "node test/tools.test.js && node test/ui.test.js && node test/entrada.test.js && node test/transparencia.test.js && node test/permissao.test.js && node test/compatibilidade.test.js && node test/skills.test.js && node test/estudio.test.js && node test/voz.test.js && node test/modo.test.js && node test/pasta.test.js && node test/catalogo.test.js && node test/desktop.test.js && node test/effort.test.js && node test/regressao.test.js && node test/memoria-conversa.test.js && node test/repeticao.test.js && node test/referencia.test.js && node test/parar.test.js && node test/continuar.test.js && node test/pipeline.test.js && node test/app.test.js && node test/aplicativo.test.js && node test/conta.test.mjs && node test/nuvem.test.js && node test/prazo.test.js && node test/primeira-vez.test.js && node test/janela.test.js && node test/pareamento.test.js && node test/fala.test.js && node test/especialistas.test.js && node test/empurrao.test.js && node test/terminal-novo.test.js && node test/markdown.test.js && node test/coerencia.test.js"
|
|
12
12
|
},
|
|
13
13
|
"engines": {
|
|
14
14
|
"node": ">=18.17.0"
|
|
@@ -39,5 +39,8 @@
|
|
|
39
39
|
"!studio/arquivos",
|
|
40
40
|
"!studio/midia",
|
|
41
41
|
"!studio/saida"
|
|
42
|
-
]
|
|
42
|
+
],
|
|
43
|
+
"primocode": {
|
|
44
|
+
"servidorMinimo": "8.12.0"
|
|
45
|
+
}
|
|
43
46
|
}
|