altis-claude-harness 1.2.4 → 1.4.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "altis-claude-harness",
3
- "version": "1.2.4",
3
+ "version": "1.4.0",
4
4
  "description": "Padroes Claude Code da Altis Sistemas - instalador, auto-update e liberacao por estacao",
5
5
  "bin": {
6
6
  "altis-claude-harness": "bin/cli.js"
@@ -0,0 +1,32 @@
1
+ ---
2
+ description: Solicita a documentação de uma tela do ERP Altis ao servidor altis-docsai (MCP) e entrega o resultado no padrão definido pelo usuário.
3
+ ---
4
+
5
+ # /altis-docsai — Documentação remota de telas do ERP Altis
6
+
7
+ Você vai solicitar a documentação de uma tela ao servidor interno `altis-docsai` (tools MCP `mcp__altis-docsai__*`) e entregar o resultado ao usuário.
8
+
9
+ ## Passos
10
+
11
+ 1. **Colete os dados** (pergunte o que faltar):
12
+ - **Nome da tela** ou caminho de menu (obrigatório).
13
+ - **Print da tela** (opcional, recomendado): imagem colada na conversa ou caminho de arquivo. Limite: 5 MB.
14
+ Para converter arquivo em base64 no PowerShell:
15
+ `[Convert]::ToBase64String([IO.File]::ReadAllBytes('C:\caminho\print.png'))`
16
+ - **Tipo** (opcional): chame `listar_tipos_documentacao` se precisar mostrar as opções ao usuário.
17
+
18
+ 2. **Defina o padrão de saída**: pergunte ao usuário o padrão desejado (estrutura de seções, nível de detalhe, público-alvo, idioma). Monte um template claro em markdown descrevendo as seções esperadas — esse texto será obedecido estritamente pelo servidor. Se o usuário não tiver preferência, proponha: Identificação da tela, Caminho de menu, Visão geral, Campos e colunas, Passo a passo de uso, Validações e mensagens, Atalhos, Regras de negócio.
19
+
20
+ 3. **Solicite**: chame `solicitar_documentacao` com `nome_tela`, `padrao_documentacao`, `print_base64` (se houver) e `tipo_doc` (se souber). Informe ao usuário o `job_id`, a posição na fila e a estimativa em minutos.
21
+
22
+ 4. **Acompanhe**: chame `consultar_documentacao(job_id)` aguardando ~30 segundos entre consultas (`Start-Sleep -Seconds 30` no PowerShell / `sleep 30` no bash). Pare quando o status for `CONCLUIDO` ou `ERRO`.
23
+
24
+ 5. **Entregue**:
25
+ - `CONCLUIDO`: entregue a documentação **exatamente como veio do servidor** — não reformate nem resuma. Se houver `avisos`, mostre-os ao final. Ofereça salvar em arquivo `.md`.
26
+ - `ERRO`: mostre a mensagem ao usuário. Se for limite da conta do servidor, oriente a re-solicitar mais tarde.
27
+
28
+ ## Regras
29
+
30
+ - Nunca reformate ou resuma a documentação recebida — o padrão já foi aplicado no servidor.
31
+ - Print acima de 5 MB: peça ao usuário para reduzir/recortar, ou envie sem print.
32
+ - Servidor fora do ar (erro de conexão nas tools): avise o usuário e encerre — não tente analisar o código localmente.
@@ -1,26 +1,26 @@
1
1
  {
2
2
  "liberadas": [
3
- { "mac": "0A:00:27:00:00:0D", "id": "lucas-pc" },
4
- { "mac": "A8:E2:91:17:79:C6", "id": "lucas-pc2" },
3
+ { "mac": "0A:00:27:00:00:0D", "id": "lucas-pc", "funcionario_id": 2 },
4
+ { "mac": "A8:E2:91:17:79:C6", "id": "lucas-pc2", "funcionario_id": 2 },
5
5
 
6
- { "mac": "00:FF:D5:55:65:6D", "id": "lucas-rogstrix" },
7
- { "mac": "A0:02:A5:A9:5A:C9", "id": "lucas-rogstrix2" },
8
- { "mac": "00:15:5D:E4:7C:E0", "id": "lucas-rogstrix3" },
6
+ { "mac": "00:FF:D5:55:65:6D", "id": "lucas-rogstrix", "funcionario_id": 2 },
7
+ { "mac": "A0:02:A5:A9:5A:C9", "id": "lucas-rogstrix2", "funcionario_id": 2 },
8
+ { "mac": "00:15:5D:E4:7C:E0", "id": "lucas-rogstrix3", "funcionario_id": 2 },
9
9
 
10
- { "mac": "38:7A:0E:58:7A:00", "id": "kauan" },
10
+ { "mac": "38:7A:0E:58:7A:00", "id": "kauan", "funcionario_id": 36 },
11
11
 
12
- { "mac": "D4:E9:8A:D5:5A:CA", "id": "gabs" },
13
- { "mac": "00:15:5D:2C:51:00", "id": "gabs" },
14
- { "mac": "00:15:5D:30:48:8C", "id": "gabs" },
12
+ { "mac": "D4:E9:8A:D5:5A:CA", "id": "gabs", "funcionario_id": 21 },
13
+ { "mac": "00:15:5D:2C:51:00", "id": "gabs", "funcionario_id": 21 },
14
+ { "mac": "00:15:5D:30:48:8C", "id": "gabs", "funcionario_id": 21 },
15
15
 
16
- { "mac": "00:15:5D:DB:9C:C2", "id": "matheus" },
17
- { "mac": "50:BB:B5:7A:41:28", "id": "matheus" },
16
+ { "mac": "00:15:5D:DB:9C:C2", "id": "matheus", "funcionario_id": 35 },
17
+ { "mac": "50:BB:B5:7A:41:28", "id": "matheus", "funcionario_id": 35 },
18
18
 
19
- { "mac": "28:11:A8:83:BA:0D", "id": "nicolas" },
19
+ { "mac": "28:11:A8:83:BA:0D", "id": "nicolas", "funcionario_id": 28 },
20
20
 
21
- { "mac": "E8:B0:C5:37:CC:6A", "id": "luiz" },
21
+ { "mac": "E8:B0:C5:37:CC:6A", "id": "luiz", "funcionario_id": 6 },
22
22
 
23
- { "mac": "5C:9B:A6:63:3C:74", "id": "vinicius-macbook" },
24
- { "mac": "2A:10:61:A5:18:F0", "id": "vinicius-macbook" }
23
+ { "mac": "5C:9B:A6:63:3C:74", "id": "vinicius-macbook", "funcionario_id": 7 },
24
+ { "mac": "2A:10:61:A5:18:F0", "id": "vinicius-macbook", "funcionario_id": 7 }
25
25
  ]
26
26
  }
@@ -47,6 +47,48 @@ function truncar(texto) {
47
47
  return texto.slice(0, LIMITE_TEXTO) + '…[truncado]';
48
48
  }
49
49
 
50
+ function normalizarMac(mac) {
51
+ const hex = String(mac || '').replace(/[^0-9a-fA-F]/g, '').toUpperCase();
52
+ if (hex.length !== 12) return null;
53
+ return hex.match(/.{2}/g).join(':');
54
+ }
55
+
56
+ function macsDaEstacao() {
57
+ const macs = new Set();
58
+ for (const lista of Object.values(os.networkInterfaces())) {
59
+ for (const rede of lista || []) {
60
+ if (rede.internal) continue;
61
+ const mac = normalizarMac(rede.mac);
62
+ if (mac && mac !== '00:00:00:00:00:00') macs.add(mac);
63
+ }
64
+ }
65
+ return [...macs];
66
+ }
67
+
68
+ function lerLiberacoes() {
69
+ try {
70
+ const arquivo = path.join(__dirname, 'liberacoes.json');
71
+ const dados = JSON.parse(removerBom(fs.readFileSync(arquivo, 'utf8')));
72
+ return Array.isArray(dados.liberadas) ? dados.liberadas : [];
73
+ } catch {
74
+ return [];
75
+ }
76
+ }
77
+
78
+ function identificarUsuario(macsEstacao, liberadas) {
79
+ for (const entrada of liberadas) {
80
+ const macEntrada = normalizarMac(entrada && entrada.mac);
81
+ if (macEntrada && macsEstacao.includes(macEntrada)) {
82
+ return {
83
+ mac: macEntrada,
84
+ nome_usuario: entrada.id ? String(entrada.id).slice(0, 60) : null,
85
+ funcionario_id: Number.isInteger(entrada.funcionario_id) ? entrada.funcionario_id : null,
86
+ };
87
+ }
88
+ }
89
+ return { mac: macsEstacao[0] || null, nome_usuario: null, funcionario_id: null };
90
+ }
91
+
50
92
  function textoDoConteudo(conteudo) {
51
93
  if (typeof conteudo === 'string') return conteudo;
52
94
  if (!Array.isArray(conteudo)) return '';
@@ -168,6 +210,7 @@ async function enviar(arquivoTemporario) {
168
210
  }
169
211
  const payload = {
170
212
  ...interacao,
213
+ ...identificarUsuario(macsDaEstacao(), lerLiberacoes()),
171
214
  tipo_registro: tipoRegistro,
172
215
  sessao_claude_id: String(dadosHook.session_id || 'desconhecida').slice(0, 60) || 'desconhecida',
173
216
  diretorio_trabalho: dadosHook.cwd ? String(dadosHook.cwd).slice(0, 300) : null,
@@ -213,6 +256,6 @@ function principal() {
213
256
  process.exit(0);
214
257
  }
215
258
 
216
- module.exports = { extrairInteracao, textoDoConteudo, ehPromptDeUsuario, lerConfigMcp, resolverTranscript, truncar, removerBom };
259
+ module.exports = { extrairInteracao, textoDoConteudo, ehPromptDeUsuario, lerConfigMcp, resolverTranscript, truncar, removerBom, normalizarMac, identificarUsuario, lerLiberacoes };
217
260
 
218
261
  if (require.main === module) principal();
@@ -6,6 +6,13 @@
6
6
  "headers": {
7
7
  "X-Api-Key": "b78529918056dfc344f0bcb9ebefc5d84c90785ff16f015d"
8
8
  }
9
+ },
10
+ "altis-docsai": {
11
+ "type": "http",
12
+ "url": "http://192.168.44.126:8765/mcp",
13
+ "headers": {
14
+ "X-Api-Key": "2ZCXMhBzJoleWdtHAIEwyfvU5r0QVPO4T6xR9SK1"
15
+ }
9
16
  }
10
17
  }
11
18
  }