auroq-os 2.8.2 → 2.8.5
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/como-funciona.md +12 -2
- package/.auroq-core/core-config.yaml +1 -1
- package/.claude/commands/AuroqOS/agents/ops.md +4 -8
- package/.claude/hooks/auroq-ate-o-fim.cjs +102 -0
- package/.claude/rules/operacao-autonoma.md +2 -1
- package/.claude/rules/project-tracker.md +2 -2
- package/.claude/settings.json +15 -3
- package/AGENTS.md +2 -0
- package/CHANGELOG.md +37 -0
- package/README.md +53 -52
- package/bin/auroq-os.js +14 -14
- package/installer/install.ps1 +2 -2
- package/installer/install.sh +2 -2
- package/lib/cofre.js +111 -22
- package/lib/onepassword.js +318 -23
- package/lib/runtime-integrity.json +13 -9
- package/package.json +2 -2
- package/scripts/runtime-integrity.mjs +1 -1
- package/seeds/business/cockpit.md +9 -0
package/bin/auroq-os.js
CHANGED
|
@@ -236,7 +236,7 @@ function mudouAlgoDeAbertura(antes, depois) {
|
|
|
236
236
|
// permissions (modo sem pedir permissao), statusLine, env e hooks proprios. Agora: o que o modelo
|
|
237
237
|
// controla vem do modelo; permissions/statusLine/env do aluno ficam; chave que o modelo nao tem
|
|
238
238
|
// fica; hooks do aluno ficam e os do framework sao trocados pelos do modelo, sem duplicar.
|
|
239
|
-
const HOOK_DO_FRAMEWORK = /(?:^|[\s"'\\/])(?:auroq-sync|synapse-engine|ahi-capture|precompact-session-digest)\.cjs\b/;
|
|
239
|
+
const HOOK_DO_FRAMEWORK = /(?:^|[\s"'\\/])(?:auroq-sync|auroq-ate-o-fim|synapse-engine|ahi-capture|precompact-session-digest)\.cjs\b/;
|
|
240
240
|
// Gancho de IA do sistema (type "prompt", sem `command`): o texto comeca com uma marca `[auroq-...]`.
|
|
241
241
|
// Sem ela, a manutencao o tomava por gancho do aluno e o duplicava a cada versao.
|
|
242
242
|
const MARCA_DO_FRAMEWORK = /^\s*\[auroq-[a-z-]+\]/;
|
|
@@ -405,7 +405,7 @@ async function applySecretProtections(targetDir) {
|
|
|
405
405
|
try { hasRemote = execFileSync('git', ['remote'], { cwd: targetDir, encoding: 'utf8' }).trim().length > 0; } catch { /* sem git */ }
|
|
406
406
|
if (hasRemote) {
|
|
407
407
|
warn(`${GOLD}IMPORTANTE: esses arquivos podem ja ter subido pro GitHub em commits antigos.${RESET}`);
|
|
408
|
-
warn(`${GOLD}Troque as chaves que estavam neles — peca ajuda ao
|
|
408
|
+
warn(`${GOLD}Troque as chaves que estavam neles — peca ajuda ao Companion: "minhas chaves do vault${RESET}`);
|
|
409
409
|
warn(`${GOLD}podem ter vazado no git, me ajuda a trocar e limpar".${RESET}`);
|
|
410
410
|
}
|
|
411
411
|
}
|
|
@@ -565,7 +565,7 @@ async function runHealthChecks(targetDir) {
|
|
|
565
565
|
if (await synapseDesatualizado(targetDir)) {
|
|
566
566
|
// Aviso, nao trava: um clone de negocio antigo traz o arquivo velho pelo git e so a
|
|
567
567
|
// manutencao nesta maquina (ou na outra, depois entregue) troca.
|
|
568
|
-
warn('Synapse antigo nesta pasta (erro "hookEventName" a cada mensagem). Peca ao
|
|
568
|
+
warn('Synapse antigo nesta pasta (erro "hookEventName" a cada mensagem). Peca ao Companion: "atualiza o sistema".');
|
|
569
569
|
}
|
|
570
570
|
if (passed === HEALTH_CHECKS.length) {
|
|
571
571
|
success(`${passed}/${HEALTH_CHECKS.length} verificacoes OK`);
|
|
@@ -603,7 +603,7 @@ async function runDoctor(targetDir, { leve = false } = {}) {
|
|
|
603
603
|
success(`Arquivos do sistema: ${HEALTH_CHECKS.length}/${HEALTH_CHECKS.length} no lugar`);
|
|
604
604
|
} else {
|
|
605
605
|
error(`Arquivos do sistema: faltam ${faltando}`);
|
|
606
|
-
problemas.push('Peca ao
|
|
606
|
+
problemas.push('Peca ao Companion, no Claude Code ou no Codex: "atualiza o sistema" (a manutencao vai repor o que falta).');
|
|
607
607
|
}
|
|
608
608
|
if (!(await synapseRegistrado(targetDir))) {
|
|
609
609
|
error('O hook do Synapse nao esta registrado: as regras do sistema nao chegam ao modelo');
|
|
@@ -611,7 +611,7 @@ async function runDoctor(targetDir, { leve = false } = {}) {
|
|
|
611
611
|
}
|
|
612
612
|
if (await synapseDesatualizado(targetDir)) {
|
|
613
613
|
error('Synapse antigo: o Claude Code recusa as regras a cada mensagem ("hookEventName")');
|
|
614
|
-
problemas.push('Peca ao
|
|
614
|
+
problemas.push('Peca ao Companion, no Claude Code ou no Codex: "atualiza o sistema" (a manutencao troca o Synapse antigo). Reserva, so se o Companion nao abrir: npx -y auroq-os@latest manutencao na pasta.');
|
|
615
615
|
}
|
|
616
616
|
|
|
617
617
|
// 2. O motor — e, principalmente, se quem abre pelo icone vai enxergar ele.
|
|
@@ -1694,7 +1694,7 @@ async function init({ pasta = null, maintenance = false, modoAgente = false, mig
|
|
|
1694
1694
|
log('');
|
|
1695
1695
|
log(`${BOLD}Entao o caminho certo NAO e instalar do zero — e clonar o que ja existe.${RESET}`);
|
|
1696
1696
|
log('');
|
|
1697
|
-
log('O seu negocio ja vive no GitHub
|
|
1697
|
+
log('O seu negocio ja vive no GitHub.');
|
|
1698
1698
|
log('Instalar do zero aqui criaria um segundo Auroq desconectado do primeiro.');
|
|
1699
1699
|
log('');
|
|
1700
1700
|
log(`Rode: ${CYAN}npx auroq-os clone${RESET}`);
|
|
@@ -1846,6 +1846,7 @@ async function init({ pasta = null, maintenance = false, modoAgente = false, mig
|
|
|
1846
1846
|
'.claude/hooks/ahi/auth-config.cjs',
|
|
1847
1847
|
'.claude/hooks/precompact-session-digest.cjs',
|
|
1848
1848
|
'.claude/hooks/auroq-sync.cjs',
|
|
1849
|
+
'.claude/hooks/auroq-ate-o-fim.cjs', // 2.8.4 — freio de comando no lugar do gancho de IA
|
|
1849
1850
|
|
|
1850
1851
|
// Synapse domain files
|
|
1851
1852
|
'.synapse/manifest',
|
|
@@ -2118,7 +2119,7 @@ async function init({ pasta = null, maintenance = false, modoAgente = false, mig
|
|
|
2118
2119
|
try {
|
|
2119
2120
|
execSync('node scripts/sync-codex-skills.mjs --clean', { cwd: targetDir, stdio: 'pipe' });
|
|
2120
2121
|
execSync('node scripts/sync-codex-skills.mjs --check', { cwd: targetDir, stdio: 'pipe' });
|
|
2121
|
-
success('Codex CLI pronto — skills locais verificadas ($companion, $
|
|
2122
|
+
success('Codex CLI pronto — skills locais verificadas ($companion, $consultor, etc.)');
|
|
2122
2123
|
} catch (e) {
|
|
2123
2124
|
warn('Sync de skills do Codex falhou — rode "npx auroq-os sync-codex" para diagnosticar');
|
|
2124
2125
|
// Sem o motivo, o suporte so via o efeito ("Codex Companion faltando") e nunca a causa.
|
|
@@ -2219,8 +2220,7 @@ ${DIM} Suas customizacoes (sobrevivem a todo update):${RESET}
|
|
|
2219
2220
|
${CYAN}.claude/settings.local.json${RESET} ${DIM}— suas configuracoes locais${RESET}
|
|
2220
2221
|
|
|
2221
2222
|
${DIM} Agentes core disponiveis:${RESET}
|
|
2222
|
-
${PURPLE}/auroq-companion${RESET} ${DIM}— Chefe da sua equipe: fale com ele, ele aciona o resto${RESET}
|
|
2223
|
-
${PURPLE}/AuroqOS:agents:ops${RESET} ${DIM}— O tecnico: instala, atualiza, conserta e conecta${RESET}
|
|
2223
|
+
${PURPLE}/auroq-companion${RESET} ${DIM}— Chefe da sua equipe: fale com ele, ele aciona o resto e cuida do tecnico${RESET}
|
|
2224
2224
|
${PURPLE}/auroq-organizer${RESET} ${DIM}— Organizacao e backup${RESET}
|
|
2225
2225
|
|
|
2226
2226
|
${DIM} Meta Squads (criadores de agentes; o Companion chama quando precisa):${RESET}
|
|
@@ -2391,7 +2391,7 @@ ${DIM} Uma vez so, nesta maquina:${RESET}
|
|
|
2391
2391
|
|
|
2392
2392
|
${CYAN}cd ${destName}${RESET}
|
|
2393
2393
|
${CYAN}claude${RESET} ${DIM}ou${RESET} ${CYAN}codex${RESET}
|
|
2394
|
-
${CYAN}/
|
|
2394
|
+
${CYAN}/auroq-companion${RESET}
|
|
2395
2395
|
${CYAN}*conectar-cofre${RESET} ${DIM}— reconectar o cofre de senhas (1Password ou Infisical gratis; ele pergunta qual)${RESET}
|
|
2396
2396
|
${DIM}(dono do negocio: se o sistema pedir login em algum momento, ${RESET}${CYAN}npx auroq-os login${RESET}${DIM})${RESET}
|
|
2397
2397
|
|
|
@@ -2417,7 +2417,7 @@ const command = process.argv[2];
|
|
|
2417
2417
|
if (['init', 'install', 'update'].includes(command)) {
|
|
2418
2418
|
error('Comando aposentado. Nada foi instalado ou alterado.');
|
|
2419
2419
|
error('Primeira instalacao: https://arcane.arka.education/auroq');
|
|
2420
|
-
error('No negocio existente, peca ao
|
|
2420
|
+
error('No negocio existente, peca ao Companion, no Claude Code ou no Codex: "atualiza o sistema". Conteudo chega pelo MCP.');
|
|
2421
2421
|
error(`Diagnostico: npx -y auroq-os@${PKG_VERSION} doctor. Reserva no terminal: npx -y auroq-os@${PKG_VERSION} manutencao.`);
|
|
2422
2422
|
process.exitCode = 1;
|
|
2423
2423
|
} else if (command === 'instalar' || command === 'manutencao') {
|
|
@@ -2552,7 +2552,7 @@ if (['init', 'install', 'update'].includes(command)) {
|
|
|
2552
2552
|
try {
|
|
2553
2553
|
execSync('node scripts/sync-codex-skills.mjs --clean', { cwd: process.cwd(), stdio: 'inherit' });
|
|
2554
2554
|
execSync('node scripts/sync-codex-skills.mjs --check', { cwd: process.cwd(), stdio: 'inherit' });
|
|
2555
|
-
success('Skills locais do Codex atualizadas e verificadas. Use $companion, $
|
|
2555
|
+
success('Skills locais do Codex atualizadas e verificadas. Use $companion, $consultor, ...');
|
|
2556
2556
|
} catch (err) {
|
|
2557
2557
|
error(`Falha ao sincronizar skills do Codex: ${err.message}`);
|
|
2558
2558
|
process.exit(1);
|
|
@@ -2567,13 +2567,13 @@ if (['init', 'install', 'update'].includes(command)) {
|
|
|
2567
2567
|
log(` ${CYAN}logout${RESET} Encerrar sessao local`);
|
|
2568
2568
|
log(` ${CYAN}whoami${RESET} Mostrar usuario autenticado`);
|
|
2569
2569
|
log(` ${CYAN}check-access${RESET} Validar acesso ativo (online; exit 0=ativo, 1=bloqueado)`);
|
|
2570
|
-
log(` ${CYAN}manutencao${RESET} Atualizar o motor e a conexao MCP (caminho normal: peca ao
|
|
2570
|
+
log(` ${CYAN}manutencao${RESET} Atualizar o motor e a conexao MCP (caminho normal: peca ao Companion "atualiza o sistema")`);
|
|
2571
2571
|
log(` ${CYAN}doctor${RESET} Diagnostico: arquivos, Node, MCP arcane, login e servidor`);
|
|
2572
2572
|
log(` ${CYAN}register-mcp${RESET} Reescrever o registro do conteudo ao vivo (MCP arcane) no projeto`);
|
|
2573
2573
|
log(` ${CYAN}sync-codex${RESET} Gerar e verificar as skills locais do Codex CLI ($nome)`);
|
|
2574
2574
|
log(` ${CYAN}historico${RESET} Estado da captura do trabalho (prevista nos Termos de Uso; desliga em Minha Conta)`);
|
|
2575
2575
|
log(` ${CYAN}conectar-cofre${RESET} Escolher e conectar o cofre de senhas: 1Password (pago, recomendado) ou Infisical (gratis)`);
|
|
2576
|
-
log(` ${CYAN}conectar-1password${RESET} Conectar o 1Password (cria o cofre e a chave sozinho; voce so aprova uma vez no app)`);
|
|
2576
|
+
log(` ${CYAN}conectar-1password${RESET} Conectar o 1Password (cria o cofre e a chave sozinho; voce so aprova uma vez no app; --instalar-app instala o app)`);
|
|
2577
2577
|
log(` ${CYAN}segredo${RESET} Ler, gravar, listar ou apagar uma credencial no cofre do aluno (vale para 1Password e Infisical)`);
|
|
2578
2578
|
log('');
|
|
2579
2579
|
log(`${DIM}Primeira instalacao: https://arcane.arka.education/auroq${RESET}`);
|
package/installer/install.ps1
CHANGED
|
@@ -589,7 +589,7 @@ function Invoke-AuroqLogin {
|
|
|
589
589
|
# sucesso. Usado como pergunta de sim/nao, ele dizia "voce ja estava logado"
|
|
590
590
|
# pra quem nunca logou, pulava o portao e deixava a conta sem acesso chegar ate
|
|
591
591
|
# a criacao da pasta.
|
|
592
|
-
& (Get-AuroqNpx) -y auroq-os@2.8.
|
|
592
|
+
& (Get-AuroqNpx) -y auroq-os@2.8.5 check-access
|
|
593
593
|
if ($LASTEXITCODE -ne 0) {
|
|
594
594
|
Write-AuroqLog 'login' 'recusado'
|
|
595
595
|
Write-Host ''
|
|
@@ -677,7 +677,7 @@ function Invoke-AuroqInit {
|
|
|
677
677
|
if ($env:AUROQ_INSTALL_DRY_RUN) { Write-AuroqOk 'Sistema - seria montado aqui'; return }
|
|
678
678
|
|
|
679
679
|
Set-Location $script:AuroqPastaAlvo
|
|
680
|
-
& (Get-AuroqNpx) -y auroq-os@2.8.
|
|
680
|
+
& (Get-AuroqNpx) -y auroq-os@2.8.5 instalar
|
|
681
681
|
if ($LASTEXITCODE -ne 0) {
|
|
682
682
|
Write-AuroqLog 'init' 'falhou'
|
|
683
683
|
Write-AuroqErro 'A montagem do sistema parou no meio.' 'Rode o mesmo comando de novo. Se repetir, mande pro suporte o arquivo install.log da pasta .auroq.'
|
package/installer/install.sh
CHANGED
|
@@ -219,9 +219,9 @@ auroq_tem_terminal() {
|
|
|
219
219
|
# recebem pedaco do script no lugar da resposta dele.
|
|
220
220
|
auroq_npx_aluno() {
|
|
221
221
|
if [ -t 0 ]; then
|
|
222
|
-
npx -y auroq-os@2.8.
|
|
222
|
+
npx -y auroq-os@2.8.5 "$@"
|
|
223
223
|
else
|
|
224
|
-
npx -y auroq-os@2.8.
|
|
224
|
+
npx -y auroq-os@2.8.5 "$@" < /dev/tty
|
|
225
225
|
fi
|
|
226
226
|
}
|
|
227
227
|
|
package/lib/cofre.js
CHANGED
|
@@ -50,9 +50,11 @@ const ESCOLHA_MSG = 'Quer o 1Password (uns 3 dolares por mes, confira o preco na
|
|
|
50
50
|
|
|
51
51
|
// Codigos do comando `segredo` (stderr: AUROQ_ERRO codigo=<c> mensagem="...").
|
|
52
52
|
// `uso` = uso errado da linha de comando (ref faltando, valor em argumento, opcao desconhecida).
|
|
53
|
+
// `op-nao-achado` = Windows: o programa `op` do 1Password nao foi achado nesta janela nem depois de recompor o PATH.
|
|
54
|
+
// Sai 1 (erro geral, como `credencial-indisponivel`), NAO 4: com 4 o agente roda a rota A de novo e cai no laco.
|
|
53
55
|
const SEGREDO_CODIGOS = ['nome-invalido', 'cofre-nao-configurado', 'nao-encontrado', 'sem-valor', 'ja-existe-confirmar',
|
|
54
|
-
'credencial-invalida', 'credencial-indisponivel', 'sem-permissao', 'rede', 'limite', 'bloqueada', 'falha', 'uso'];
|
|
55
|
-
// Saida: 0 ok, 1 erro geral, 2 uso errado, 3 nao encontrado, 4 cofre nao configurado.
|
|
56
|
+
'credencial-invalida', 'credencial-indisponivel', 'op-nao-achado', 'sem-permissao', 'rede', 'limite', 'bloqueada', 'falha', 'uso'];
|
|
57
|
+
// Saida: 0 ok, 1 erro geral (inclui op-nao-achado), 2 uso errado, 3 nao encontrado, 4 cofre nao configurado.
|
|
56
58
|
const SEGREDO_EXIT = Object.freeze({ ok: 0, erro: 1, uso: 2, 'nao-encontrado': 3, 'cofre-nao-configurado': 4 });
|
|
57
59
|
const CODIGOS_DE_USO = new Set(['uso', 'nome-invalido', 'sem-valor', 'ja-existe-confirmar']);
|
|
58
60
|
|
|
@@ -81,6 +83,11 @@ function envOf(d) {
|
|
|
81
83
|
return (d && d.env) || process.env;
|
|
82
84
|
}
|
|
83
85
|
|
|
86
|
+
/** Windows? (`d.platform` troca nos testes.) */
|
|
87
|
+
function ehWindows(d) {
|
|
88
|
+
return ((d && d.platform) || process.platform) === 'win32';
|
|
89
|
+
}
|
|
90
|
+
|
|
84
91
|
function nowOf(d) {
|
|
85
92
|
return d && typeof d.now === 'function' ? d.now() : Date.now();
|
|
86
93
|
}
|
|
@@ -387,6 +394,10 @@ function opReference(ref) {
|
|
|
387
394
|
|
|
388
395
|
// ─── Mensagens por codigo ────────────────────────────────
|
|
389
396
|
|
|
397
|
+
// Windows, `op` fora do PATH desta janela: primeiro fechar e abrir o programa (o PATH novo so chega a processos novos);
|
|
398
|
+
// a rota A so se isso nao resolver (rodar a rota A de novo logo de cara e o laco que o teste real viveu).
|
|
399
|
+
const MSG_OP_NAO_ACHADO = 'O programa do 1Password (op) nao foi achado nesta janela. Se ele foi instalado agora ha pouco, feche e abra o programa (Claude Code, Codex ou o app) e tente de novo. Se continuar, rode UMA vez: npx auroq-os conectar-cofre --cofre 1password --agente (ele confere o programa e instala se faltar); se ele disser ja-conectado e isto voltar, peca ajuda ao Arcano com este codigo: op-nao-achado.';
|
|
400
|
+
|
|
390
401
|
function messageFor(codigo, tipo, detalhe = '') {
|
|
391
402
|
const nome = NOME_TIPO[tipo] || 'cofre';
|
|
392
403
|
switch (codigo) {
|
|
@@ -402,6 +413,8 @@ function messageFor(codigo, tipo, detalhe = '') {
|
|
|
402
413
|
}
|
|
403
414
|
case 'credencial-indisponivel':
|
|
404
415
|
return `Nao consegui usar a chave deste computador no ${nome} agora. Tente de novo em alguns minutos.`;
|
|
416
|
+
case 'op-nao-achado':
|
|
417
|
+
return MSG_OP_NAO_ACHADO;
|
|
405
418
|
case 'sem-permissao':
|
|
406
419
|
return `A chave do agente nao tem permissao para isso no ${nome}.`;
|
|
407
420
|
case 'rede':
|
|
@@ -430,7 +443,9 @@ const OP_PERMISSION_RE = /(forbidden|permission|not allowed|insufficient|denied|
|
|
|
430
443
|
function classifyOp(d, r, secrets = []) {
|
|
431
444
|
const o = mod(d, 'onepassword');
|
|
432
445
|
const stderr = String((r && r.stderr) || '');
|
|
433
|
-
|
|
446
|
+
// sem o `op`: no Windows (ja tentou recompor o PATH) e "nao achei o programa", que rodar a rota A de novo NAO resolve;
|
|
447
|
+
// fora dele segue como sempre foi
|
|
448
|
+
if (r && r.missing) return { codigo: ehWindows(d) ? 'op-nao-achado' : 'cofre-nao-configurado', detalhe: '' };
|
|
434
449
|
if (OP_NOT_VAULT_RE.test(stderr)) return { codigo: 'cofre-nao-configurado', detalhe: '' };
|
|
435
450
|
if (OP_AMBIGUOUS_RE.test(stderr)) return { codigo: 'falha', detalhe: `Tem mais de um item com esse nome no cofre ${VAULT_NAME}; apague ou renomeie o repetido.` };
|
|
436
451
|
if (OP_NOT_FOUND_RE.test(stderr)) return { codigo: 'nao-encontrado', detalhe: '' };
|
|
@@ -472,24 +487,52 @@ function findField(fields, campo) {
|
|
|
472
487
|
function makeOpBackend(d) {
|
|
473
488
|
const tipo = '1password';
|
|
474
489
|
|
|
475
|
-
|
|
490
|
+
const validToken = (t) => {
|
|
491
|
+
const o = mod(d, 'onepassword');
|
|
492
|
+
return t && o.isValidToken(String(t).trim()) ? String(t).trim() : null;
|
|
493
|
+
};
|
|
494
|
+
const fromEnv = () => validToken(envOf(d)[mod(d, 'onepassword').TOKEN_VAR]);
|
|
495
|
+
async function fromDisk() {
|
|
476
496
|
const o = mod(d, 'onepassword');
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
497
|
+
try { return validToken(await (d.readOpToken ? d.readOpToken() : o.readPersistedToken())); } catch { return null; }
|
|
498
|
+
}
|
|
499
|
+
async function token() {
|
|
500
|
+
return fromEnv() || fromDisk();
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// Windows: o `op` instalado DEPOIS de o programa-pai abrir (winget so muda o PATH no registro) nao esta no PATH deste
|
|
504
|
+
// processo: o spawn da ENOENT. Recompoe o PATH UMA vez por backend (cada recomposicao abre o PowerShell) e tenta o
|
|
505
|
+
// comando de novo; chamadas em paralelo esperam a mesma recomposicao. Devolve false se nao ha como recompor.
|
|
506
|
+
let recomposicao = null;
|
|
507
|
+
function recomporPathUmaVez() {
|
|
508
|
+
if (!recomposicao) {
|
|
509
|
+
recomposicao = (async () => {
|
|
510
|
+
const o = mod(d, 'onepassword');
|
|
511
|
+
const recompor = typeof d.refreshPath === 'function' ? d.refreshPath : o.refreshWindowsPath;
|
|
512
|
+
if (typeof recompor !== 'function') return false;
|
|
513
|
+
try { await recompor(); } catch { /* melhor esforco: o comando decide se achou */ }
|
|
514
|
+
return true;
|
|
515
|
+
})();
|
|
516
|
+
}
|
|
517
|
+
return recomposicao;
|
|
481
518
|
}
|
|
482
519
|
|
|
483
520
|
async function call(tk, args, input = '') {
|
|
484
521
|
const o = mod(d, 'onepassword');
|
|
485
522
|
const run = d.op || o.runOp;
|
|
486
|
-
//
|
|
487
|
-
const
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
523
|
+
// o ambiente e montado a cada tentativa: o PATH recomposto vale so para quem copia process.env DEPOIS
|
|
524
|
+
const tentar = () => {
|
|
525
|
+
// `isolate`: o agente nunca pode cair na janela da digital do app; vale so a chave
|
|
526
|
+
const env = o.opEnv(String(tk).trim(), { isolate: true });
|
|
527
|
+
// a chave do Infisical (ID e segredo) nao tem nada a ver com o `op`: nao vai para o ambiente dele
|
|
528
|
+
for (const k of Object.keys(env)) {
|
|
529
|
+
if (/^AUROQ_INFISICAL_/i.test(k)) delete env[k];
|
|
530
|
+
}
|
|
531
|
+
return run(args, { env, input, timeoutMs: OP_TIMEOUT_MS });
|
|
532
|
+
};
|
|
533
|
+
let r = await tentar();
|
|
534
|
+
if (r && r.missing && ehWindows(d) && (await recomporPathUmaVez())) r = await tentar();
|
|
535
|
+
return r;
|
|
493
536
|
}
|
|
494
537
|
|
|
495
538
|
const semChave = () => failure('cofre-nao-configurado', tipo);
|
|
@@ -501,12 +544,34 @@ function makeOpBackend(d) {
|
|
|
501
544
|
});
|
|
502
545
|
|
|
503
546
|
async function run(args, input, secrets) {
|
|
504
|
-
|
|
547
|
+
let tk = await token();
|
|
505
548
|
if (!tk) return { erro: semChave() };
|
|
506
|
-
|
|
549
|
+
let r = await call(tk, args, input);
|
|
550
|
+
let c = r.ok ? null : classifyOp(d, r, secrets);
|
|
551
|
+
// A variavel do programa pode estar velha: janela aberta com uma chave que depois foi revogada e trocada (a
|
|
552
|
+
// nova esta gravada no computador). Chave RECUSADA vinda da variavel => tenta a gravada, se for outra. So esta
|
|
553
|
+
// recusa clara conta; rede, limite ou o que for nao muda de chave.
|
|
554
|
+
if (c && c.codigo === 'credencial-invalida' && tk === fromEnv()) {
|
|
555
|
+
const gravada = await fromDisk();
|
|
556
|
+
if (gravada && gravada !== tk) {
|
|
557
|
+
const r2 = await call(gravada, args, input);
|
|
558
|
+
tk = gravada;
|
|
559
|
+
r = r2;
|
|
560
|
+
c = r.ok ? null : classifyOp(d, r, secrets);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
507
563
|
if (r.ok) return { r, tk };
|
|
508
|
-
const
|
|
509
|
-
|
|
564
|
+
const erro = failure(c.codigo, tipo, c.detalhe);
|
|
565
|
+
// Campos extras so para quem precisa saber a causa (a migracao); nenhum entra na mensagem do `segredo`.
|
|
566
|
+
// `semOp`: o programa nem rodou. `diag`: o que o `op` disse (stderr, uma linha, sem a chave nem o valor gravado:
|
|
567
|
+
// oneLine tira ops_..., o token e os segredos que esta execucao conhece). Nunca o stdout.
|
|
568
|
+
if (r.missing) {
|
|
569
|
+
erro.semOp = true;
|
|
570
|
+
} else {
|
|
571
|
+
const diag = oneLine(r.stderr, 160, [...(secrets || []), tk, tk.replace(/^ops_/, '')]);
|
|
572
|
+
if (diag) erro.diag = diag;
|
|
573
|
+
}
|
|
574
|
+
return { erro };
|
|
510
575
|
}
|
|
511
576
|
|
|
512
577
|
const backend = {
|
|
@@ -1281,6 +1346,24 @@ function migracao(status, codigo, mensagem, n = {}) {
|
|
|
1281
1346
|
return { status, codigo, movidos: n.movidos || 0, iguais: n.iguais || 0, falhas: n.falhas || 0, mensagem };
|
|
1282
1347
|
}
|
|
1283
1348
|
|
|
1349
|
+
// Mensagens do 'conectar-1password-primeiro': cada uma diz o que de fato aconteceu. Com o complemento do `op` (diagDoOp)
|
|
1350
|
+
// ainda cabem nos 400 caracteres da linha AUROQ_RESULTADO (o texto corta ali).
|
|
1351
|
+
const ROTA_A = 'npx auroq-os conectar-cofre --cofre 1password --agente';
|
|
1352
|
+
// A chave NAO foi achada (nem na variavel do programa nem gravada no computador).
|
|
1353
|
+
const MSG_MIGRAR_SEM_CHAVE = `Nao achei a chave do 1Password nesta janela (nem na variavel do programa nem no que o computador tem gravado). Rode: ${ROTA_A} (se a chave ja estiver gravada ele responde ja-conectado na hora). Se responder ja-conectado e esta mensagem voltar, feche e abra o programa e rode a migracao de novo.`;
|
|
1354
|
+
// A chave foi achada e o 1Password disse que ela nao vale.
|
|
1355
|
+
const MSG_MIGRAR_CHAVE_RECUSADA = `O 1Password recusou a chave gravada neste computador (revogada ou invalida). Rode: ${ROTA_A} (ele cria outra) e depois a migracao de novo.`;
|
|
1356
|
+
// A chave foi achada e o `op` rodou, mas o cofre Claude nao aparece para ela (ou ela nao tem permissao nele).
|
|
1357
|
+
const MSG_MIGRAR_COFRE_INVISIVEL = `A chave do 1Password foi achada, mas nao enxerga o cofre ${VAULT_NAME}. Rode: ${ROTA_A}. Depois rode a migracao de novo.`;
|
|
1358
|
+
// A chave foi achada, mas o programa `op` nao existe aqui (fora do Windows; no Windows e o codigo op-nao-achado).
|
|
1359
|
+
const MSG_MIGRAR_SEM_OP = `A chave do 1Password foi achada, mas o programa do 1Password (op) nao foi achado neste computador. Rode: ${ROTA_A}. Depois rode a migracao de novo.`;
|
|
1360
|
+
|
|
1361
|
+
/** " (O 1Password disse: ...)" com a linha que o `op` devolveu (guardada na falha); '' se nao ha. Nunca traz a chave nem o valor. */
|
|
1362
|
+
function diagDoOp(falha) {
|
|
1363
|
+
const linha = falha && typeof falha.diag === 'string' ? falha.diag.trim() : '';
|
|
1364
|
+
return linha ? ` (O 1Password disse: ${linha})` : '';
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1284
1367
|
/**
|
|
1285
1368
|
* Leva as chaves do Infisical para o cofre Claude do 1Password e, so se TUDO foi, troca o cofre ativo (e a UNICA
|
|
1286
1369
|
* coisa que troca para o 1Password quem ja usa o Infisical: conectar o 1Password sozinho nao troca). Nao apaga
|
|
@@ -1304,13 +1387,19 @@ async function migrar(options = {}, d = {}) {
|
|
|
1304
1387
|
return migracao('erro', 'origem-indisponivel', 'O Infisical nao esta conectado neste computador, entao nao tenho de onde levar as chaves.');
|
|
1305
1388
|
}
|
|
1306
1389
|
if (!(await destino.pronto())) {
|
|
1307
|
-
return migracao('aguardando', 'conectar-1password-primeiro',
|
|
1390
|
+
return migracao('aguardando', 'conectar-1password-primeiro', MSG_MIGRAR_SEM_CHAVE);
|
|
1308
1391
|
}
|
|
1309
1392
|
// o cofre Claude precisa estar visivel para a chave do 1Password
|
|
1310
1393
|
const vis = await destino.listar();
|
|
1311
1394
|
if (!vis.ok) {
|
|
1312
|
-
|
|
1313
|
-
|
|
1395
|
+
// programa `op` nao achado (Windows): rodar a rota A de novo nao resolve (e foi o laco de "conectar primeiro")
|
|
1396
|
+
if (vis.codigo === 'op-nao-achado') return migracao('aguardando', 'op-nao-achado', vis.mensagem);
|
|
1397
|
+
if (vis.codigo === 'credencial-invalida') {
|
|
1398
|
+
return migracao('aguardando', 'conectar-1password-primeiro', `${MSG_MIGRAR_CHAVE_RECUSADA}${diagDoOp(vis)}`);
|
|
1399
|
+
}
|
|
1400
|
+
if (vis.semOp) return migracao('aguardando', 'conectar-1password-primeiro', MSG_MIGRAR_SEM_OP); // fora do Windows: a rota A confere o programa
|
|
1401
|
+
if (['cofre-nao-configurado', 'sem-permissao'].includes(vis.codigo)) {
|
|
1402
|
+
return migracao('aguardando', 'conectar-1password-primeiro', `${MSG_MIGRAR_COFRE_INVISIVEL}${diagDoOp(vis)}`);
|
|
1314
1403
|
}
|
|
1315
1404
|
return migracao('erro', 'falha', `Nao consegui olhar o cofre ${VAULT_NAME} do 1Password agora (${vis.codigo}). Tente de novo em alguns minutos.`);
|
|
1316
1405
|
}
|