auroq-os 2.3.0 → 2.3.2

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 (2) hide show
  1. package/bin/auroq-os.js +102 -1
  2. package/package.json +1 -1
package/bin/auroq-os.js CHANGED
@@ -183,8 +183,103 @@ async function runHealthChecks(targetDir) {
183
183
  return { passed, total: HEALTH_CHECKS.length };
184
184
  }
185
185
 
186
+ /**
187
+ * `doctor` — o diagnostico que o suporte pede primeiro. Existe por causa do NFR-06:
188
+ * a falha do MCP e silenciosa (conteudo simplesmente nao aparece), entao alguem
189
+ * precisa perguntar em voz alta se o caminho inteiro esta de pe.
190
+ */
191
+ async function runDoctor(targetDir) {
192
+ showBanner();
193
+ log(`${BOLD}Diagnostico do Auroq${RESET}`);
194
+ log('');
195
+
196
+ const problemas = [];
197
+
198
+ // 1. arquivos de autoload
199
+ let faltando = 0;
200
+ for (const [file] of HEALTH_CHECKS) {
201
+ if (!(await fs.pathExists(path.join(targetDir, file)))) faltando++;
202
+ }
203
+ if (faltando === 0) {
204
+ success(`Arquivos do sistema: ${HEALTH_CHECKS.length}/${HEALTH_CHECKS.length} no lugar`);
205
+ } else {
206
+ error(`Arquivos do sistema: faltam ${faltando}`);
207
+ problemas.push('Rode *update-auroq dentro do Claude Code pra repor o que falta.');
208
+ }
209
+
210
+ // 2. Node visivel pra quem abre pelo icone (NFR-06 — o caso real de falha)
211
+ try {
212
+ const v = execSync('npx --version', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
213
+ success(`Node/npx no caminho: npx ${v}`);
214
+ } catch {
215
+ error('Node/npx nao encontrado no caminho deste programa');
216
+ problemas.push('O app do Claude aberto pelo icone nao enxerga o Node. Abra o Ops e peca o *bootstrap, ou abra o Claude pelo Terminal.');
217
+ }
218
+
219
+ // 3. registro do MCP nos dois runtimes
220
+ const mcpPath = path.join(targetDir, '.mcp.json');
221
+ let pin = null;
222
+ if (await fs.pathExists(mcpPath)) {
223
+ try {
224
+ const json = await fs.readJSON(mcpPath);
225
+ pin = json?.mcpServers?.arcane?.args?.find(a => String(a).startsWith('arcane-mcp@')) || null;
226
+ } catch { /* arquivo corrompido cai no erro abaixo */ }
227
+ }
228
+ if (pin) {
229
+ success(`MCP arcane registrado no Claude Code (${pin})`);
230
+ } else {
231
+ error('MCP arcane nao registrado em .mcp.json');
232
+ problemas.push('Rode *update-auroq — ele reescreve o registro do MCP.');
233
+ }
234
+ const tomlPath = path.join(targetDir, '.codex', 'config.toml');
235
+ const temToml = (await fs.pathExists(tomlPath)) &&
236
+ (await fs.readFile(tomlPath, 'utf8')).includes('[mcp_servers.arcane]');
237
+ if (temToml) success('MCP arcane registrado no Codex');
238
+ else log(` ${DIM}MCP arcane ainda nao registrado no Codex (so importa se voce usa o Codex)${RESET}`);
239
+
240
+ // 4. login e licenca — o unico jeito de saber se o conteudo vai chegar
241
+ const credPath = path.join(require('os').homedir(), '.arcane', 'credentials.json');
242
+ let cred = null;
243
+ try {
244
+ if (await fs.pathExists(credPath)) cred = await fs.readJSON(credPath);
245
+ } catch { /* arquivo ilegivel = tratado como sem login */ }
246
+ if (cred?.user?.email) {
247
+ success(`Logado como ${cred.user.email}`);
248
+ } else {
249
+ error('Voce nao esta logado');
250
+ problemas.push('Rode: npx arcane-mcp login (mesmo email e senha da plataforma).');
251
+ }
252
+
253
+ // 5. o servidor do conteudo responde?
254
+ try {
255
+ const r = await fetch('https://arcane.arka.education/api/mcp/verify', { method: 'POST' });
256
+ if (r.status === 401) {
257
+ success('Servidor do conteudo respondendo (pediu login, como esperado)');
258
+ } else if (r.ok) {
259
+ success('Servidor do conteudo respondendo');
260
+ } else {
261
+ error(`Servidor do conteudo respondeu ${r.status}`);
262
+ problemas.push('O conteudo ao vivo pode estar fora do ar. Seus arquivos locais continuam funcionando.');
263
+ }
264
+ } catch {
265
+ error('Sem resposta do servidor do conteudo');
266
+ problemas.push('Confira sua internet. Sem servidor, o conteudo ao vivo nao chega — o resto do Auroq continua.');
267
+ }
268
+
269
+ log('');
270
+ if (problemas.length === 0) {
271
+ success('Tudo certo. Pode chamar o Companion.');
272
+ return 0;
273
+ }
274
+ error(`${problemas.length} coisa(s) pra resolver:`);
275
+ for (const p of problemas) log(` ${DIM}- ${p}${RESET}`);
276
+ log('');
277
+ log(`${DIM}Se travar, chame o suporte: 11 97312-2273${RESET}`);
278
+ return 1;
279
+ }
280
+
186
281
  async function writeArcaneMcpConfig(targetDir) {
187
- const pin = 'arcane-mcp@0.1.0';
282
+ const pin = 'arcane-mcp@0.2.0';
188
283
  const mcpPath = path.join(targetDir, '.mcp.json');
189
284
  let json = { mcpServers: {} };
190
285
  if (await fs.pathExists(mcpPath)) {
@@ -927,6 +1022,11 @@ if (command === 'init' || command === 'install') {
927
1022
  error(`Falha ao conectar 1Password: ${e.message}`);
928
1023
  process.exit(1);
929
1024
  });
1025
+ } else if (command === 'doctor' || command === 'diagnostico') {
1026
+ runDoctor(process.cwd()).then(code => process.exit(code)).catch(e => {
1027
+ error(`Falha no diagnostico: ${e.message}`);
1028
+ process.exit(1);
1029
+ });
930
1030
  } else if (command === 'sync-codex') {
931
1031
  // Regenera as skills do Codex CLI a partir dos comandos atuais do projeto.
932
1032
  try {
@@ -948,6 +1048,7 @@ if (command === 'init' || command === 'install') {
948
1048
  log(` ${CYAN}whoami${RESET} Mostrar usuario autenticado`);
949
1049
  log(` ${CYAN}check-access${RESET} Validar acesso ativo (online; exit 0=ativo, 1=bloqueado)`);
950
1050
  log(` ${CYAN}update${RESET} Atualizar (via Ops dentro do Claude Code)`);
1051
+ log(` ${CYAN}doctor${RESET} Diagnostico: arquivos, Node, MCP arcane, login e servidor`);
951
1052
  log(` ${CYAN}sync-codex${RESET} Gerar e verificar as skills locais do Codex CLI ($nome)`);
952
1053
  log(` ${CYAN}conectar-1password${RESET} Conectar o 1Password CLI (token lido do Ctrl+C, nunca digitado)`);
953
1054
  log('');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auroq-os",
3
- "version": "2.3.0",
3
+ "version": "2.3.2",
4
4
  "description": "Auroq OS — Sistema Operacional de IA para Experts",
5
5
  "bin": {
6
6
  "auroq-os": "bin/auroq-os.js"