auroq-os 2.4.18 → 2.4.20
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/.auroq-core/core-config.yaml +1 -1
- package/CHANGELOG.md +26 -0
- package/bin/auroq-os.js +73 -14
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.4.20] — 2026-09-04
|
|
4
|
+
|
|
5
|
+
### Dentro do Codex no Windows: "UNABLE_TO_VERIFY_LEAF_SIGNATURE" (EMB-028, causa vista na tela)
|
|
6
|
+
Com o motivo tecnico na mensagem (0.4.1), a aluna mostrou: dentro do Codex a conexao com o
|
|
7
|
+
servidor cai porque o Node nao confia no certificado que chega — algo entre o Codex e a internet
|
|
8
|
+
(antivirus, proxy ou o sandbox do Codex) reassina a conexao com um certificado que o Windows
|
|
9
|
+
conhece e o Node, por padrao, nao. No terminal funciona porque o ambiente carrega a confianca;
|
|
10
|
+
o Codex abre o MCP com ambiente minimo (openai/codex#29124).
|
|
11
|
+
- **`arcane-mcp@0.4.2`** (pin novo) confia tambem nos certificados do sistema, sem flag.
|
|
12
|
+
- **Registro do Codex** no Windows ganha `NODE_USE_SYSTEM_CA = '1'` e repassa, se existirem,
|
|
13
|
+
`NODE_EXTRA_CA_CERTS`, `SSL_CERT_FILE`, `SSL_CERT_DIR`, `NODE_OPTIONS`, `HTTPS_PROXY`,
|
|
14
|
+
`HTTP_PROXY`, `NO_PROXY`.
|
|
15
|
+
- **`doctor`** fecha o relatorio pedindo ao proprio Codex do aluno pra chamar o conteudo ao vivo
|
|
16
|
+
e imprime a resposta — o teste definitivo, na mesma tela.
|
|
17
|
+
|
|
18
|
+
## [2.4.19] — 2026-09-04
|
|
19
|
+
|
|
20
|
+
### O npx guarda cache por ambiente — o Codex abria "a frio" mesmo depois de aquecido
|
|
21
|
+
Medido em Windows limpo: com o pacote ja baixado no PowerShell (2s), a primeira abertura com o
|
|
22
|
+
ambiente que o Codex da ao MCP ainda levava 45-53s. Cada ambiente tem o seu cache. E o que
|
|
23
|
+
explica a aluna ver timeout (30s) ontem e "ferramenta indisponivel" hoje, com o `doctor` limpo.
|
|
24
|
+
- `init`, `update` e `register-mcp` aquecem os DOIS ambientes no Windows: o do terminal e o
|
|
25
|
+
do Codex (minimo + variaveis do registro).
|
|
26
|
+
- O `doctor` ja abria "como o Codex abre" (2.4.18); agora esse passo usa exatamente o mesmo
|
|
27
|
+
ambiente do aquecimento, entao ele tambem prepara a maquina.
|
|
28
|
+
|
|
3
29
|
## [2.4.18] — 2026-09-04
|
|
4
30
|
|
|
5
31
|
### Doctor faz o trabalho do suporte numa tela so (Codex)
|
package/bin/auroq-os.js
CHANGED
|
@@ -426,7 +426,16 @@ async function runDoctor(targetDir) {
|
|
|
426
426
|
log(` ${DIM}Ultimas linhas do log do Codex sobre o arcane:${RESET}`);
|
|
427
427
|
for (const l of rastro) log(` ${DIM} ${l}${RESET}`);
|
|
428
428
|
}
|
|
429
|
-
|
|
429
|
+
let codexFalhou = false;
|
|
430
|
+
if (vCodex) {
|
|
431
|
+
log(` ${DIM}Pedindo ao proprio Codex pra chamar o conteudo ao vivo (pode levar 1-2 min)...${RESET}`);
|
|
432
|
+
const linhas = rodarNoCodex(targetDir);
|
|
433
|
+
const texto = linhas.join('\n');
|
|
434
|
+
codexFalhou = !/versao|catalogo_listar \(completed\)/i.test(texto) || /motivo t[eé]cnico|indispon[ií]vel|failed|timed out/i.test(texto);
|
|
435
|
+
(codexFalhou ? error : success)(codexFalhou ? 'Codex de verdade: NAO conseguiu usar o conteudo ao vivo' : 'Codex de verdade: usou o conteudo ao vivo');
|
|
436
|
+
for (const l of linhas) log(` ${DIM} ${l}${RESET}`);
|
|
437
|
+
}
|
|
438
|
+
if (r.subiu === null || !r.temForja || !r.chamada || r.chamada.erro || codexFalhou) {
|
|
430
439
|
problemas.push('Mande o print desta tela INTEIRA pro suporte (11 93621-4486) — ela ja traz tudo que precisamos.');
|
|
431
440
|
}
|
|
432
441
|
}
|
|
@@ -450,8 +459,11 @@ async function runDoctor(targetDir) {
|
|
|
450
459
|
// (rede domestica + antivirus) a aluna viu timeout em todas as que fez. Por isso:
|
|
451
460
|
// (1) o registro do Codex pede mais tempo, (2) instalacao/atualizacao ja baixam o
|
|
452
461
|
// pacote, (3) o doctor mede o arranque de verdade em vez de so olhar o registro.
|
|
453
|
-
const ARCANE_MCP_PIN = 'arcane-mcp@0.4.
|
|
462
|
+
const ARCANE_MCP_PIN = 'arcane-mcp@0.4.2';
|
|
454
463
|
const CODEX_MCP_STARTUP_SEC = 120;
|
|
464
|
+
const CODEX_ENV_MINIMO = ['PATH', 'PATHEXT', 'USERNAME', 'USERDOMAIN', 'USERPROFILE', 'TEMP', 'TMP',
|
|
465
|
+
'HOME', 'LOGNAME', 'SHELL', 'TERM', 'USER'];
|
|
466
|
+
|
|
455
467
|
const MCP_ARRANQUE_LIMITE_MS = 9000; // abaixo do que o Codex tolera (10s)
|
|
456
468
|
|
|
457
469
|
// No Windows o Codex abre o MCP com um ambiente minimo (PATH, USERNAME, USERPROFILE,
|
|
@@ -461,7 +473,13 @@ const MCP_ARRANQUE_LIMITE_MS = 9000; // abaixo do que o Codex tolera (10s)
|
|
|
461
473
|
const CODEX_ENV_WINDOWS = [
|
|
462
474
|
'SystemRoot', 'windir', 'COMSPEC', 'SystemDrive', 'APPDATA', 'LOCALAPPDATA',
|
|
463
475
|
'ProgramData', 'ProgramFiles', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE', 'TEMP', 'TMP',
|
|
476
|
+
// Confianca e proxy que o terminal do aluno tem e o Codex tira do MCP (openai/codex#29124).
|
|
477
|
+
'NODE_EXTRA_CA_CERTS', 'SSL_CERT_FILE', 'SSL_CERT_DIR', 'NODE_OPTIONS',
|
|
478
|
+
'HTTPS_PROXY', 'HTTP_PROXY', 'NO_PROXY',
|
|
464
479
|
];
|
|
480
|
+
// Dentro do Codex no Windows a conexao caia com UNABLE_TO_VERIFY_LEAF_SIGNATURE (04/09):
|
|
481
|
+
// o Node por padrao ignora a loja de certificados do Windows. Node >= 22.15 aceita isto.
|
|
482
|
+
const CODEX_ENV_FIXO_WINDOWS = { NODE_USE_SYSTEM_CA: '1' };
|
|
465
483
|
|
|
466
484
|
function envCodexArcane({ plataforma = process.platform, env = process.env } = {}) {
|
|
467
485
|
if (plataforma !== 'win32') return null;
|
|
@@ -472,6 +490,7 @@ function envCodexArcane({ plataforma = process.platform, env = process.env } = {
|
|
|
472
490
|
if (!valor || valor.includes("'") || /[\r\n]/.test(valor)) continue;
|
|
473
491
|
pares.push(`${nome} = '${valor}'`); // string literal do TOML: barra invertida sem escape
|
|
474
492
|
}
|
|
493
|
+
for (const [nome, valor] of Object.entries(CODEX_ENV_FIXO_WINDOWS)) pares.push(`${nome} = '${valor}'`);
|
|
475
494
|
return pares.length ? `env = { ${pares.join(', ')} }` : null;
|
|
476
495
|
}
|
|
477
496
|
|
|
@@ -489,7 +508,7 @@ function blocoCodexArcane(pin, opcoes) {
|
|
|
489
508
|
}
|
|
490
509
|
|
|
491
510
|
// Baixa o pacote do conteudo ao vivo com o MESMO nome que o registro usa (o cache do
|
|
492
|
-
// npx e por nome+versao: `arcane-mcp` e `arcane-mcp@0.4.
|
|
511
|
+
// npx e por nome+versao: `arcane-mcp` e `arcane-mcp@0.4.2` sao caches diferentes).
|
|
493
512
|
// `npx` no Windows e um .cmd: sem shell o Node recusa (EINVAL) e com `shell: true` o Node 24
|
|
494
513
|
// imprime um DeprecationWarning na tela do aluno (DEP0190). Chamar o cmd.exe direto, sem shell.
|
|
495
514
|
function comandoNpx(args) {
|
|
@@ -501,15 +520,40 @@ function comandoNpx(args) {
|
|
|
501
520
|
};
|
|
502
521
|
}
|
|
503
522
|
|
|
523
|
+
// O ambiente que o Codex da ao MCP no Windows (minimo + o env do registro). Medido em
|
|
524
|
+
// 04/09/2026 (windows-latest): o npx guarda cache POR AMBIENTE — aquecido no PowerShell
|
|
525
|
+
// (2s), a primeira abertura pelo Codex ainda levava 45-53s. Por isso aquecemos os dois.
|
|
526
|
+
function envComoCodex({ plataforma = process.platform, env = process.env } = {}) {
|
|
527
|
+
const base = {};
|
|
528
|
+
for (const k of Object.keys(env)) {
|
|
529
|
+
if (CODEX_ENV_MINIMO.some(n => n.toLowerCase() === k.toLowerCase())) base[k] = env[k];
|
|
530
|
+
}
|
|
531
|
+
if (plataforma === 'win32') {
|
|
532
|
+
for (const nome of CODEX_ENV_WINDOWS) {
|
|
533
|
+
const chave = Object.keys(env).find(k => k.toLowerCase() === nome.toLowerCase());
|
|
534
|
+
if (chave && env[chave]) base[nome] = env[chave];
|
|
535
|
+
}
|
|
536
|
+
Object.assign(base, CODEX_ENV_FIXO_WINDOWS);
|
|
537
|
+
}
|
|
538
|
+
return base;
|
|
539
|
+
}
|
|
540
|
+
|
|
504
541
|
function aquecerArcaneMcp() {
|
|
505
542
|
if (process.env.NODE_ENV === 'test' && process.env.AUROQ_SKIP_AUTH === '1') return true;
|
|
543
|
+
const c = comandoNpx(['-y', ARCANE_MCP_PIN, 'whoami']);
|
|
506
544
|
try {
|
|
507
|
-
const c = comandoNpx(['-y', ARCANE_MCP_PIN, 'whoami']);
|
|
508
545
|
execFileSync(c.cmd, c.args, { stdio: 'pipe', timeout: 240000, ...c.opts });
|
|
509
|
-
return true;
|
|
510
546
|
} catch {
|
|
511
547
|
return false;
|
|
512
548
|
}
|
|
549
|
+
if (process.platform === 'win32') {
|
|
550
|
+
try {
|
|
551
|
+
execFileSync(c.cmd, c.args, { stdio: 'pipe', timeout: 240000, env: envComoCodex(), ...c.opts });
|
|
552
|
+
} catch {
|
|
553
|
+
return false;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
return true;
|
|
513
557
|
}
|
|
514
558
|
|
|
515
559
|
// Abre o conteudo ao vivo do jeito que o Codex/Claude Code abrem e mede quanto tempo
|
|
@@ -578,8 +622,6 @@ async function guardarBootstrapLocal(targetDir, file, dst, dstExists) {
|
|
|
578
622
|
// abre o MCP com o mesmo ambiente minimo que o Codex usa no Windows (openai/codex#4180)
|
|
579
623
|
// mais o env do registro, lista as ferramentas e chama uma. Se aqui funciona e no
|
|
580
624
|
// Codex nao, o problema e do lado do Codex — e o log dele entra no relatorio.
|
|
581
|
-
const CODEX_ENV_MINIMO = ['PATH', 'PATHEXT', 'USERNAME', 'USERDOMAIN', 'USERPROFILE', 'TEMP', 'TMP',
|
|
582
|
-
'HOME', 'LOGNAME', 'SHELL', 'TERM', 'USER'];
|
|
583
625
|
|
|
584
626
|
function lerBlocoArcane(toml) {
|
|
585
627
|
const m = String(toml || '').match(/\[mcp_servers\.arcane\][\s\S]*?(?=\n\[|$(?![\s\S]))/);
|
|
@@ -601,10 +643,7 @@ function lerEnvDoBloco(bloco) {
|
|
|
601
643
|
function abrirComoCodex(pin, envBloco, limiteMs = 120000) {
|
|
602
644
|
return new Promise((resolve) => {
|
|
603
645
|
const { spawn } = require('child_process');
|
|
604
|
-
const env =
|
|
605
|
-
for (const k of Object.keys(process.env)) {
|
|
606
|
-
if (CODEX_ENV_MINIMO.some(n => n.toLowerCase() === k.toLowerCase())) env[k] = process.env[k];
|
|
607
|
-
}
|
|
646
|
+
const env = envComoCodex();
|
|
608
647
|
Object.assign(env, envBloco || {});
|
|
609
648
|
const c = comandoNpx(['-y', pin]);
|
|
610
649
|
const t0 = Date.now();
|
|
@@ -708,6 +747,26 @@ async function rastroDoCodex(limite = 8) {
|
|
|
708
747
|
}
|
|
709
748
|
}
|
|
710
749
|
|
|
750
|
+
|
|
751
|
+
// O teste definitivo: o proprio Codex do aluno chamando a ferramenta. E o unico jeito de
|
|
752
|
+
// ver o que o Codex faz com o MCP (sandbox, proxy, certificado) sem pedir print atras de print.
|
|
753
|
+
function rodarNoCodex(pasta) {
|
|
754
|
+
const prompt = 'Chame a ferramenta MCP catalogo_listar do servidor arcane e responda SOMENTE com a primeira linha do resultado, ou com a mensagem de erro exata que a ferramenta devolveu.';
|
|
755
|
+
const args = ['exec', '--skip-git-repo-check', '-C', pasta, prompt];
|
|
756
|
+
const c = process.platform === 'win32'
|
|
757
|
+
? { cmd: process.env.ComSpec || 'cmd.exe', args: ['/d', '/s', '/c', `codex exec --skip-git-repo-check -C "${pasta}" "${prompt}"`], opts: { windowsVerbatimArguments: true } }
|
|
758
|
+
: { cmd: 'codex', args, opts: {} };
|
|
759
|
+
let saida = '';
|
|
760
|
+
try {
|
|
761
|
+
saida = execFileSync(c.cmd, c.args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], timeout: 300000, ...c.opts });
|
|
762
|
+
} catch (e) {
|
|
763
|
+
saida = `${e.stdout || ''}\n${e.stderr || ''}\n[codex saiu com ${e.status ?? e.code ?? 'erro'}]`;
|
|
764
|
+
}
|
|
765
|
+
return saida.split('\n').map(l => l.replace(/\u001b\[[0-9;]*m/g, '').trim())
|
|
766
|
+
.filter(l => l && !/^hook:|^warning: Skill|usage limit|^Tip:|^tokens used|^[0-9.]+$/i.test(l))
|
|
767
|
+
.slice(-8).map(l => l.slice(0, 220));
|
|
768
|
+
}
|
|
769
|
+
|
|
711
770
|
async function writeArcaneMcpConfig(targetDir) {
|
|
712
771
|
const pin = ARCANE_MCP_PIN;
|
|
713
772
|
const mcpPath = path.join(targetDir, '.mcp.json');
|
|
@@ -1157,7 +1216,7 @@ async function init({ pasta = null } = {}) {
|
|
|
1157
1216
|
}
|
|
1158
1217
|
await patchEnableAllProjectMcpServers(targetDir);
|
|
1159
1218
|
await writeArcaneMcpConfig(targetDir);
|
|
1160
|
-
step('Preparando o conteudo ao vivo (baixa uma vez; pode levar 1-
|
|
1219
|
+
step('Preparando o conteudo ao vivo (baixa uma vez; no Windows prepara tambem pro Codex; pode levar 1-3 min)...');
|
|
1161
1220
|
if (aquecerArcaneMcp()) success('Conteudo ao vivo pronto pra abrir rapido');
|
|
1162
1221
|
else warn('Nao consegui baixar o conteudo ao vivo agora — a primeira abertura vai demorar mais');
|
|
1163
1222
|
|
|
@@ -1435,7 +1494,7 @@ async function clone(repoArg) {
|
|
|
1435
1494
|
}
|
|
1436
1495
|
|
|
1437
1496
|
await writeArcaneMcpConfig(destDir);
|
|
1438
|
-
step('Preparando o conteudo ao vivo (baixa uma vez; pode levar 1-
|
|
1497
|
+
step('Preparando o conteudo ao vivo (baixa uma vez; no Windows prepara tambem pro Codex; pode levar 1-3 min)...');
|
|
1439
1498
|
if (aquecerArcaneMcp()) success('Conteudo ao vivo pronto pra abrir rapido');
|
|
1440
1499
|
else warn('Nao consegui baixar o conteudo ao vivo agora — a primeira abertura vai demorar mais');
|
|
1441
1500
|
|
|
@@ -1596,4 +1655,4 @@ if (command === 'init' || command === 'install') {
|
|
|
1596
1655
|
log('');
|
|
1597
1656
|
}
|
|
1598
1657
|
|
|
1599
|
-
if (process.env.AUROQ_EXPORTA_INTERNOS === '1') module.exports = { blocoCodexArcane, envCodexArcane, lerBlocoArcane, lerEnvDoBloco, limparArcaneDoGlobal };
|
|
1658
|
+
if (process.env.AUROQ_EXPORTA_INTERNOS === '1') module.exports = { blocoCodexArcane, envCodexArcane, lerBlocoArcane, lerEnvDoBloco, limparArcaneDoGlobal, envComoCodex };
|