@dotrino/ia-agent 0.1.0 → 0.1.1
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/bin/cli.js +77 -32
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -1,43 +1,88 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* dotrino-ia-agent —
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* dotrino-ia-agent — agente de Dotrino IA.
|
|
4
|
+
*
|
|
5
|
+
* dotrino-ia-agent enlaza (si falta) y CORRE el agente
|
|
6
|
+
* dotrino-ia-agent enroll re-enlaza (sobrescribe) y corre el agente
|
|
7
|
+
* opciones: [--label <nombre>] [--proxy <wss://…>] [--dir <ruta>]
|
|
8
|
+
*
|
|
9
|
+
* El agente es un dispositivo enrolado del vault (label 'ia-agent'): puede vivir en
|
|
10
|
+
* cualquier máquina y aparece solo en ia.dotrino.com para chatear con tus IAs
|
|
11
|
+
* (Claude, OpenCode…). Con un solo comando queda enlazado y sirviendo.
|
|
6
12
|
*/
|
|
7
|
-
import
|
|
13
|
+
import readline from 'node:readline'
|
|
8
14
|
import { startIaAgent } from '../index.js'
|
|
15
|
+
import { enroll, parseQr, loadLink, dataDir } from '@dotrino/remote-agent/link'
|
|
9
16
|
|
|
10
|
-
const
|
|
11
|
-
const cmd =
|
|
17
|
+
const args = process.argv.slice(2)
|
|
18
|
+
const cmd = args[0] && !args[0].startsWith('-') ? args[0] : 'run'
|
|
19
|
+
const opt = (name) => { const i = args.indexOf(name); return i >= 0 ? args[i + 1] : undefined }
|
|
12
20
|
|
|
13
|
-
function
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
function ask (q) {
|
|
22
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout })
|
|
23
|
+
return new Promise((res) => rl.question(q, (a) => { rl.close(); res(a) }))
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (args.includes('-h') || args.includes('--help')) {
|
|
27
|
+
console.log(`uso:
|
|
28
|
+
dotrino-ia-agent enlaza esta máquina (si falta) y corre el agente
|
|
29
|
+
dotrino-ia-agent enroll re-enlaza (sobrescribe el enlace) y corre el agente
|
|
30
|
+
opciones: [--label <nombre>] [--proxy <wss://…>] [--dir <ruta>]
|
|
31
|
+
|
|
32
|
+
datos en ${dataDir('dotrino-ia-agent')} (override DOTRINO_REMOTE_AGENT_DIR)`)
|
|
33
|
+
process.exit(0)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function doEnroll (dir, label) {
|
|
37
|
+
console.log('Enlazar esta máquina con tu vault.')
|
|
38
|
+
console.log('El código lo generas en el CERTIFICADOR (tu vault). Hay dos formas:')
|
|
39
|
+
console.log(' · Sin vault externo → abre https://ia.dotrino.com, elige')
|
|
40
|
+
console.log(' "Usar este dispositivo como bóveda" → "Enlazar otra máquina" y copia el código.')
|
|
41
|
+
console.log(' · Con vault en un PC → ahí corre `dotrino-vault pair` y copia el QR/JSON.\n')
|
|
42
|
+
const text = await ask('Pega el código y Enter:\n> ')
|
|
43
|
+
const qr = parseQr(text)
|
|
44
|
+
console.log('\nConectando…')
|
|
45
|
+
await enroll({
|
|
46
|
+
qr,
|
|
47
|
+
dir,
|
|
48
|
+
label,
|
|
49
|
+
onChallenge: ({ deviceId, code }) => {
|
|
50
|
+
console.log('\n Escribe ESTE código en tu bóveda para aprobar esta máquina:')
|
|
51
|
+
console.log(` código: ${code}`)
|
|
52
|
+
console.log(` máquina: ${deviceId}`)
|
|
53
|
+
console.log(' (en ia.dotrino.com escríbelo en el campo y pulsa "Aprobar";')
|
|
54
|
+
console.log(` en el PC del vault: dotrino-vault approve ${code})\n`)
|
|
55
|
+
console.log(' Esperando aprobación…')
|
|
56
|
+
}
|
|
19
57
|
})
|
|
58
|
+
console.log('\n ✓ Máquina enlazada — levantando el agente…\n')
|
|
20
59
|
}
|
|
21
60
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
61
|
+
try {
|
|
62
|
+
const dir = opt('--dir')
|
|
63
|
+
const label = opt('--label') || 'ia-agent'
|
|
64
|
+
// El comando por defecto enrola SOLO si aún no está enlazada; `enroll` fuerza
|
|
65
|
+
// re-enrolar (sobrescribe) aunque ya lo esté. En ambos casos, al terminar sigue
|
|
66
|
+
// y LEVANTA el servicio.
|
|
67
|
+
if (cmd === 'enroll' || !loadLink(dir)) {
|
|
68
|
+
if (cmd === 'enroll' && loadLink(dir)) console.log('Re-enlazando esta máquina (sobrescribe el enlace actual).\n')
|
|
69
|
+
await doEnroll(dir, label)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const agent = await startIaAgent({
|
|
73
|
+
dir, proxyUrl: opt('--proxy'),
|
|
74
|
+
onRevoked: () => { console.log(' Esta máquina fue revocada desde tu bóveda. Para reconectarla, vuelve a enrolarla.\n'); process.exit(0) }
|
|
75
|
+
})
|
|
76
|
+
console.log('\n Dotrino IA — agente activo')
|
|
77
|
+
console.log(' máquina:', agent.machineId)
|
|
78
|
+
console.log(' aparece solo en ia.dotrino.com\n')
|
|
79
|
+
// Mantener vivo el servicio aunque stdin no sea una TTY (systemd/pm2/`nohup </dev/null`):
|
|
80
|
+
// los sockets del proxy están `unref`'d, así que sin este keep-alive el proceso saldría
|
|
81
|
+
// justo después de arrancar. Vive hasta SIGINT/SIGTERM (o auto-borrado por revocación).
|
|
82
|
+
const keepAlive = setInterval(() => {}, 1 << 30)
|
|
83
|
+
const bye = () => { clearInterval(keepAlive); agent.close(); process.exit(0) }
|
|
84
|
+
process.on('SIGINT', bye); process.on('SIGTERM', bye)
|
|
85
|
+
} catch (e) {
|
|
86
|
+
console.error('error:', e.message)
|
|
42
87
|
process.exit(1)
|
|
43
88
|
}
|
package/package.json
CHANGED