sijur-cli 2.0.0 → 2.1.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/README.md +27 -0
- package/bin/sijur.js +7 -0
- package/package.json +1 -1
- package/src/cmds/sessao.js +44 -3
- package/src/mcp.js +25 -2
package/README.md
CHANGED
|
@@ -126,6 +126,32 @@ sijur tarefas_encerrar --tarefa_id 123456 --relatorio "Protocolado RExt" \
|
|
|
126
126
|
--fechar_ns_entidade_pai --momento_processual 46 --dry_run
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
+
## Para um agente
|
|
130
|
+
|
|
131
|
+
Agente nao abre navegador nem marca caixa de consentimento, entao ele nao usa `sijur login`.
|
|
132
|
+
Ele leva uma chave `sk_sijur_` do escritorio numa variavel:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
export SIJUR_API_KEY=sk_sijur_...
|
|
136
|
+
sijur tools
|
|
137
|
+
sijur prazos_listar --json
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
A chave ja responde as duas perguntas que o consentimento responderia, e ambas se escolhem no
|
|
141
|
+
cadastro dela, dentro do SIJUR:
|
|
142
|
+
|
|
143
|
+
- **quais ferramentas o agente enxerga** — os escopos da chave; `sijur tools` lista exatamente isso;
|
|
144
|
+
- **em nome de quem ele escreve** — o titular da chave ("expedida em nome de"). Sem titular, o
|
|
145
|
+
trabalho sai no user-bot generico do escritorio.
|
|
146
|
+
|
|
147
|
+
Com a variavel definida ela **vence o cofre** e nada e gravado na maquina. E por isso que dois
|
|
148
|
+
agentes convivem no mesmo computador: cada um carrega a sua chave no proprio ambiente, sem disputar
|
|
149
|
+
o Keychain. `sijur login` recusa enquanto a variavel existir, para ninguem achar que trocou de
|
|
150
|
+
identidade sem ter trocado; `sijur whoami` mostra qual chave esta respondendo e o que ela alcanca.
|
|
151
|
+
|
|
152
|
+
O contexto que a CLI gasta no agente e o do catalogo sob demanda: `sijur tools` devolve uma linha
|
|
153
|
+
por ferramenta, e so a escolhida tem o schema lido, com `sijur tools <nome> --json`.
|
|
154
|
+
|
|
129
155
|
## Auditoria
|
|
130
156
|
|
|
131
157
|
Toda chamada apenda uma linha em `~/.sijur-cli/audit.jsonl`: timestamp, ferramenta, argumentos e
|
|
@@ -136,3 +162,4 @@ se deu certo.
|
|
|
136
162
|
| variavel | padrao |
|
|
137
163
|
|---|---|
|
|
138
164
|
| `SIJUR_MCP_URL` | `https://sijur.com.br/mcp` |
|
|
165
|
+
| `SIJUR_API_KEY` | (vazio) — definida, autentica com esta chave `sk_sijur_` e ignora o cofre |
|
package/bin/sijur.js
CHANGED
|
@@ -23,6 +23,13 @@ GLOBAIS
|
|
|
23
23
|
--json imprime numa linha so (o padrao e identado)
|
|
24
24
|
-h, --help esta ajuda
|
|
25
25
|
|
|
26
|
+
AGENTE
|
|
27
|
+
Um agente nao passa por tela de consentimento: em vez de "sijur login", exporte
|
|
28
|
+
SIJUR_API_KEY com uma chave sk_sijur_ do escritorio. Ela ja carrega quais
|
|
29
|
+
ferramentas o agente ve e em nome de quem ele escreve, os dois escolhidos no
|
|
30
|
+
cadastro da chave. Definida a variavel, ela vence o cofre e nada e gravado na
|
|
31
|
+
maquina — entao dois agentes convivem no mesmo computador, cada um com a sua.
|
|
32
|
+
|
|
26
33
|
CODIGOS DE SAIDA
|
|
27
34
|
0 ok 1 erro de uso 2 autenticacao/escopo 4 erro da ferramenta ou da rede
|
|
28
35
|
|
package/package.json
CHANGED
package/src/cmds/sessao.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { fazerLogin, revogar } from '../auth.js';
|
|
2
2
|
import * as cofre from '../keychain.js';
|
|
3
3
|
import { SERVIDOR, escoposSuportados } from '../config.js';
|
|
4
|
-
import { listarTools, fechar } from '../mcp.js';
|
|
4
|
+
import { listarTools, fechar, usandoChaveDoAmbiente, prefixoDaChave } from '../mcp.js';
|
|
5
5
|
|
|
6
|
-
import { EXIT, erroAuth } from '../exit.js';
|
|
6
|
+
import { EXIT, erroAuth, erroUso } from '../exit.js';
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
function emitir(obj, op) {
|
|
@@ -11,6 +11,12 @@ function emitir(obj, op) {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export async function cmdLogin(op) {
|
|
14
|
+
// WHY barrar em vez de avisar: com SIJUR_API_KEY definida a chave vence em toda chamada, entao o
|
|
15
|
+
// login gravaria no cofre e nao mudaria nada — e quem rodou ficaria achando que trocou de identidade.
|
|
16
|
+
if (usandoChaveDoAmbiente) {
|
|
17
|
+
throw erroUso('SIJUR_API_KEY esta definida: a CLI ja esta autenticando com essa chave, e o login ' +
|
|
18
|
+
'nao mudaria nada. Tire a variavel do ambiente para autenticar como pessoa.');
|
|
19
|
+
}
|
|
14
20
|
const r = await fazerLogin({ trocar: op.trocar });
|
|
15
21
|
const blob = cofre.ler();
|
|
16
22
|
const avisos = [];
|
|
@@ -36,11 +42,46 @@ export async function cmdLogout(op) {
|
|
|
36
42
|
let revogado = { revogado: false, motivo: 'nao_pedido' };
|
|
37
43
|
if (op.revogar) revogado = await revogar();
|
|
38
44
|
cofre.apagar();
|
|
39
|
-
emitir({
|
|
45
|
+
emitir({
|
|
46
|
+
ok: true,
|
|
47
|
+
credenciais_apagadas: true,
|
|
48
|
+
revogado_no_servidor: revogado.revogado,
|
|
49
|
+
detalhe: revogado,
|
|
50
|
+
avisos: usandoChaveDoAmbiente
|
|
51
|
+
? ['SIJUR_API_KEY continua definida: apaguei o cofre, mas as proximas chamadas seguem ' +
|
|
52
|
+
'autenticando com essa chave. Para parar de vez, tire a variavel do ambiente.']
|
|
53
|
+
: []
|
|
54
|
+
}, op);
|
|
40
55
|
return EXIT.OK;
|
|
41
56
|
}
|
|
42
57
|
|
|
43
58
|
export async function cmdWhoami(op) {
|
|
59
|
+
// Com chave do ambiente nao ha blob local: escopo e titular vivem no cadastro da chave, no
|
|
60
|
+
// servidor. O que a CLI pode mostrar aqui e o efeito — as ferramentas que a chave enxerga.
|
|
61
|
+
if (usandoChaveDoAmbiente) {
|
|
62
|
+
let tools = null;
|
|
63
|
+
let vivo = false;
|
|
64
|
+
try {
|
|
65
|
+
tools = await listarTools();
|
|
66
|
+
vivo = true;
|
|
67
|
+
} catch (err) {
|
|
68
|
+
tools = `nao consegui listar: ${err.message}`;
|
|
69
|
+
} finally {
|
|
70
|
+
await fechar();
|
|
71
|
+
}
|
|
72
|
+
emitir({
|
|
73
|
+
ok: vivo,
|
|
74
|
+
servidor: SERVIDOR,
|
|
75
|
+
credencial: 'chave da variavel SIJUR_API_KEY',
|
|
76
|
+
prefixo: prefixoDaChave,
|
|
77
|
+
guardado_em: 'variavel de ambiente (nada gravado nesta maquina)',
|
|
78
|
+
sessao_viva: vivo,
|
|
79
|
+
total_ferramentas: Array.isArray(tools) ? tools.length : null,
|
|
80
|
+
tools_visiveis: tools
|
|
81
|
+
}, op);
|
|
82
|
+
return vivo ? EXIT.OK : EXIT.AUTH;
|
|
83
|
+
}
|
|
84
|
+
|
|
44
85
|
const blob = cofre.ler();
|
|
45
86
|
if (!blob?.tokens?.access_token) throw erroAuth('Sem credencial nesta maquina. Rode `sijur login`.');
|
|
46
87
|
|
package/src/mcp.js
CHANGED
|
@@ -12,11 +12,21 @@ import { erroAuth, erroApi } from './exit.js';
|
|
|
12
12
|
// servidor, entao o canal so tinha custo. Sem ele, some a classe inteira de timeout.
|
|
13
13
|
// O SDK continua sendo a fonte do OAuth (`auth`), que e onde ele e solido.
|
|
14
14
|
|
|
15
|
+
// WHY chave no ambiente: agente nao passa por tela de consentimento. A chave `sk_sijur_` ja carrega
|
|
16
|
+
// o recorte de ferramentas (scopes) e o titular (mcp_api_keys.userid), ambos escolhidos no cadastro
|
|
17
|
+
// da chave — entao ELA e a credencial do agente, e o cofre fica para a pessoa no terminal. Efeito
|
|
18
|
+
// colateral desejado: sem cofre, dois agentes na mesma maquina nao disputam slot de keychain
|
|
19
|
+
// nenhum; cada um leva a sua chave no proprio ambiente.
|
|
20
|
+
const CHAVE_AMBIENTE = process.env.SIJUR_API_KEY || null;
|
|
21
|
+
export const usandoChaveDoAmbiente = !!CHAVE_AMBIENTE;
|
|
22
|
+
export const prefixoDaChave = CHAVE_AMBIENTE ? CHAVE_AMBIENTE.slice(0, 20) : null;
|
|
23
|
+
|
|
15
24
|
const PROTOCOLO = '2025-06-18';
|
|
16
25
|
let _sessao = null;
|
|
17
26
|
let _proximoId = 1;
|
|
18
27
|
|
|
19
28
|
function tokenGuardado() {
|
|
29
|
+
if (CHAVE_AMBIENTE) return CHAVE_AMBIENTE;
|
|
20
30
|
return cofre.ler()?.tokens?.access_token || null;
|
|
21
31
|
}
|
|
22
32
|
|
|
@@ -63,9 +73,18 @@ async function postar(corpo, { token, sessao }) {
|
|
|
63
73
|
// Uma tentativa; devolve { resposta, token } ja com renovacao feita se tomou 401.
|
|
64
74
|
async function postarComRenovacao(corpo, sessao) {
|
|
65
75
|
let token = tokenGuardado();
|
|
66
|
-
if (!token)
|
|
76
|
+
if (!token) {
|
|
77
|
+
throw erroAuth('Sem credencial nesta maquina. Rode `sijur login`, ou exporte ' +
|
|
78
|
+
'SIJUR_API_KEY com uma chave sk_sijur_ se quem chama e um agente.');
|
|
79
|
+
}
|
|
67
80
|
let r = await postar(corpo, { token, sessao });
|
|
68
81
|
if (r.status === 401) {
|
|
82
|
+
// WHY nao renovar com chave do ambiente: `sk_sijur_` nao tem refresh. Cair no fluxo OAuth aqui
|
|
83
|
+
// trocaria "a chave foi recusada" por um erro sobre login, que nao e o que aconteceu.
|
|
84
|
+
if (CHAVE_AMBIENTE) {
|
|
85
|
+
throw erroAuth('A chave em SIJUR_API_KEY foi recusada (401). Confira se ela existe, ' +
|
|
86
|
+
'nao expirou e nao foi revogada.');
|
|
87
|
+
}
|
|
69
88
|
token = await renovarToken();
|
|
70
89
|
r = await postar(corpo, { token, sessao });
|
|
71
90
|
if (r.status === 401) throw erroAuth('Token recusado pelo servidor. Rode `sijur login`.');
|
|
@@ -104,7 +123,11 @@ const RE_SCOPE = /Scope insuficiente\.?\s*Requer:\s*([^\s"'}]+)/i;
|
|
|
104
123
|
|
|
105
124
|
function checarEscopo(texto) {
|
|
106
125
|
const m = RE_SCOPE.exec(texto || '');
|
|
107
|
-
if (m)
|
|
126
|
+
if (!m) return;
|
|
127
|
+
// Com chave do ambiente o escopo se conserta no cadastro da chave, nao com `sijur login`.
|
|
128
|
+
throw erroAuth(CHAVE_AMBIENTE
|
|
129
|
+
? `Escopo faltando: ${m[1]}. A chave em SIJUR_API_KEY nao tem esse escopo — inclua-o no cadastro dela.`
|
|
130
|
+
: `Escopo faltando: ${m[1]}. Rode \`sijur login\` para reautorizar com esse escopo.`);
|
|
108
131
|
}
|
|
109
132
|
|
|
110
133
|
export const chamarBruto = (nome, argumentos) => _chamar(nome, argumentos, true);
|