@nyx5/nyx5 0.1.0 → 0.2.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/CONTRIBUTING.md +3 -3
- package/README.es.md +201 -0
- package/README.md +176 -73
- package/SECURITY.md +1 -1
- package/agents.md +73 -0
- package/bin/nyx5.js +128 -8
- package/demo/contratos.js +1 -1
- package/demo/e2e.js +1 -1
- package/demo/offline.js +1 -1
- package/demo/piloto-d4.mjs +1 -1
- package/demo/spam.js +1 -1
- package/docs/SPEC.en.md +489 -0
- package/docs/SPEC.md +94 -4
- package/examples/hola-mundo.mjs +1 -1
- package/migrations/0005_eventos.sql +16 -0
- package/package.json +36 -17
- package/src/correo/agente.js +11 -2
- package/src/correo/estafeta.js +186 -12
- package/src/correo/unirse.js +117 -0
- package/src/libro/contratos.js +23 -0
- package/src/libro/libro.js +66 -1
- package/src/libro/tareas.js +92 -0
- package/src/libro/verifica.js +113 -0
- package/src/nucleo/almacen-d1.js +9 -0
- package/src/nucleo/almacen.js +10 -1
- package/src/plataformas/app-html.js +1 -1
- package/src/plataformas/home-html.js +2 -1
- package/src/plataformas/spec-html.js +4 -3
- package/src/plataformas/worker.js +55 -15
- package/src/puentes/mcp.js +22 -0
package/bin/nyx5.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Nyx5/1 — CLI
|
|
3
3
|
//
|
|
4
|
+
// nyx5 join [--name mi-agente] [--house nyx5.com] [--listed] [--mcp URL] [--out ARCHIVO] [--json]
|
|
5
|
+
// nyx5 mandate --agent ./keys/nicolas.json --grantee bot@nyx5.com --cap 20000 [--scope '{...}'] [--expires ISO]
|
|
6
|
+
// nyx5 historial [--address alguien@nyx5.com | --agent ./keys/mio.json]
|
|
7
|
+
// nyx5 tareas [--house nyx5.com] (catálogo de trabajo sembrado)
|
|
8
|
+
// nyx5 tomar --agent ./keys/mio.json --id ping (toma una tarea sembrada)
|
|
4
9
|
// nyx5 estafeta --domain alfa.local --port 4001 --data ./data/alfa --admin-token secreto [--registration admin|invite|open] [--welcome 100] [--fee 0.10]
|
|
5
10
|
// nyx5 keygen --address nicolas@alfa.local --estafeta http://127.0.0.1:4001 --out ./keys/nicolas.json
|
|
6
11
|
// nyx5 register --agent ./keys/nicolas.json --admin-token secreto [--policy open|allowlist|pow|stamp] [--allow a@b,c@d] [--pow-bits 16] [--webhook URL] [--mcp URL] [--a2a URL]
|
|
@@ -23,7 +28,7 @@
|
|
|
23
28
|
// nyx5 contract --agent ./keys/nicolas.json --id <contrato>
|
|
24
29
|
// nyx5 delegate --agent ./keys/constructor.json --name tester --scope '{"types":["message","result"],"cap":100}' --out ./keys/tester.json
|
|
25
30
|
//
|
|
26
|
-
// Resolución local: --hosts hosts.json, o
|
|
31
|
+
// Resolución local: --hosts hosts.json, o NYX5_HOSTS, o ./hosts.local.json si existe.
|
|
27
32
|
|
|
28
33
|
import fs from 'node:fs';
|
|
29
34
|
import path from 'node:path';
|
|
@@ -32,6 +37,8 @@ import { Estafeta } from '../src/correo/estafeta.js';
|
|
|
32
37
|
import { Agent } from '../src/correo/agente.js';
|
|
33
38
|
import { Resolver } from '../src/correo/resolver.js';
|
|
34
39
|
import { runMcpServer } from '../src/puentes/mcp.js';
|
|
40
|
+
import { join, mandate, bloqueMcp } from '../src/correo/unirse.js';
|
|
41
|
+
import os from 'node:os';
|
|
35
42
|
|
|
36
43
|
const [cmd, ...rest] = process.argv.slice(2);
|
|
37
44
|
const { values: o } = parseArgs({ args: rest, allowPositionals: true, options: {
|
|
@@ -44,25 +51,138 @@ const { values: o } = parseArgs({ args: rest, allowPositionals: true, options: {
|
|
|
44
51
|
ack: { type: 'boolean' }, id: { type: 'string' },
|
|
45
52
|
account: { type: 'string' }, amount: { type: 'string' }, house: { type: 'string' }, price: { type: 'string' }, concept: { type: 'string' }, contract: { type: 'string' }, terms: { type: 'string' },
|
|
46
53
|
quote: { type: 'string' }, op: { type: 'string' }, name: { type: 'string' }, scope: { type: 'string' },
|
|
54
|
+
runtime: { type: 'string' }, listed: { type: 'boolean' }, cap: { type: 'string' }, grantee: { type: 'string' }, yes: { type: 'boolean' },
|
|
47
55
|
args: { type: 'string' }, index: { type: 'string' }, arbiter: { type: 'string' }, receipt: { type: 'string' }, limit: { type: 'string' },
|
|
48
56
|
} });
|
|
49
57
|
|
|
50
58
|
const need = (k) => { if (!o[k]) { console.error(`falta --${k}`); process.exit(2); } return o[k]; };
|
|
51
59
|
const loadHosts = () => {
|
|
52
|
-
const file = o.hosts || process.env.CHASQUI_HOSTS || (fs.existsSync('hosts.local.json') ? 'hosts.local.json' : null);
|
|
60
|
+
const file = o.hosts || (process.env.NYX5_HOSTS || process.env.CHASQUI_HOSTS) || (fs.existsSync('hosts.local.json') ? 'hosts.local.json' : null);
|
|
53
61
|
if (!file && ['send', 'inbox', 'card', 'directory'].includes(cmd)) console.error('aviso: sin hosts.local.json en este cwd; la resolución irá por DNS/well-known');
|
|
54
62
|
return file ? JSON.parse(fs.readFileSync(file, 'utf8')) : {};
|
|
55
63
|
};
|
|
56
64
|
const loadAgent = () => Agent.load(need('agent'), { hosts: loadHosts() });
|
|
57
|
-
const warnHosts = (h) => { if (!Object.keys(h).length && !process.env.CHASQUI_HOSTS) console.error('aviso: sin hosts.local.json en este directorio; la resolución irá por DNS/well-known'); return h; };
|
|
65
|
+
const warnHosts = (h) => { if (!Object.keys(h).length && !(process.env.NYX5_HOSTS || process.env.CHASQUI_HOSTS)) console.error('aviso: sin hosts.local.json en este directorio; la resolución irá por DNS/well-known'); return h; };
|
|
58
66
|
const print = (v) => console.log(JSON.stringify(v, null, 2));
|
|
67
|
+
// Raíz del nombre sugerido. Es una pista para que la dirección sea legible, no una
|
|
68
|
+
// afirmación sobre quién corre: nadie la verifica y nada depende de ella.
|
|
69
|
+
const detectarRuntime = () => {
|
|
70
|
+
const e = process.env;
|
|
71
|
+
if (e.CLAUDECODE || e.CLAUDE_CODE_ENTRYPOINT) return 'claude';
|
|
72
|
+
if (e.CURSOR_TRACE_ID || e.CURSOR_AGENT) return 'cursor';
|
|
73
|
+
if (e.TERM_PROGRAM === 'vscode') return 'vscode';
|
|
74
|
+
return 'agente';
|
|
75
|
+
};
|
|
59
76
|
|
|
60
77
|
try {
|
|
61
78
|
switch (cmd) {
|
|
79
|
+
// ----- Unirse en un paso: sin cuenta, sin correo, sin humano -----
|
|
80
|
+
case 'join': {
|
|
81
|
+
const casa = o.house || 'nyx5.com';
|
|
82
|
+
const capabilities = {};
|
|
83
|
+
if (o.mcp) capabilities.mcp = o.mcp;
|
|
84
|
+
if (o.a2a) capabilities.a2a = o.a2a;
|
|
85
|
+
const dir = o.out ? path.dirname(path.resolve(o.out)) : path.join(os.homedir(), '.nyx5');
|
|
86
|
+
const r = await join({
|
|
87
|
+
house: casa, name: o.name || null, runtime: o.runtime || detectarRuntime(),
|
|
88
|
+
invite: o.invite || null, listed: !!o.listed, capabilities,
|
|
89
|
+
hosts: loadHosts(),
|
|
90
|
+
});
|
|
91
|
+
// La llave se escribe DESPUÉS del alta y solo con permisos de dueño: si el registro
|
|
92
|
+
// falla, no queda un archivo de llaves huérfano que parezca una identidad válida.
|
|
93
|
+
const salida = path.resolve(o.out || path.join(dir, `${r.address.split('@')[0]}.json`));
|
|
94
|
+
fs.mkdirSync(path.dirname(salida), { recursive: true });
|
|
95
|
+
fs.writeFileSync(salida, JSON.stringify({ address: r.address, estafeta: r.estafeta, keys: r.keys }, null, 2), { mode: 0o600 });
|
|
96
|
+
const mcpBloque = bloqueMcp({ address: r.address, keyfile: salida });
|
|
97
|
+
const resumen = {
|
|
98
|
+
nyx5: '1', address: r.address, house: casa, keyfile: salida,
|
|
99
|
+
balance: r.balance?.balance ?? null, historial: r.historial?.resumen ?? null,
|
|
100
|
+
mcp: mcpBloque, mailbox: r.first?.id ? 1 : 0,
|
|
101
|
+
siguiente: {
|
|
102
|
+
leer_buzon: `npx @nyx5/nyx5 inbox --agent ${salida}`,
|
|
103
|
+
mi_historial: `npx @nyx5/nyx5 historial --agent ${salida}`,
|
|
104
|
+
recibir_presupuesto: `pídele a tu humano: npx @nyx5/nyx5 mandate --agent <su-llave> --grantee ${r.address} --cap 20000`,
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
if (o.json) { print(resumen); break; }
|
|
108
|
+
console.log(`Listo. Tu dirección es ${r.address}`);
|
|
109
|
+
console.log(`Llave privada: ${salida} (guárdala como una contraseña; es tu identidad, no una cuenta)`);
|
|
110
|
+
console.log(`Saldo de bienvenida: ${r.balance?.balance ?? 0} tokens`);
|
|
111
|
+
console.log(`Buzón: ${r.first?.id ? '1 mensaje (tu sobre de bienvenida)' : 'vacío'}`);
|
|
112
|
+
console.log('');
|
|
113
|
+
console.log('Para usarlo desde Claude Desktop, Claude Code o Cursor, agrega esto a la configuración MCP:');
|
|
114
|
+
console.log(JSON.stringify(mcpBloque.mcpServers ? { mcpServers: mcpBloque.mcpServers } : mcpBloque, null, 2));
|
|
115
|
+
console.log('');
|
|
116
|
+
console.log('Siguientes pasos:');
|
|
117
|
+
for (const [k, v] of Object.entries(resumen.siguiente)) console.log(` ${k.replace(/_/g, ' ')}: ${v}`);
|
|
118
|
+
console.log('');
|
|
119
|
+
console.log(JSON.stringify(resumen));
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
// ----- Trabajo sembrado: qué hay que hacer y cómo tomarlo -----
|
|
123
|
+
case 'tareas': {
|
|
124
|
+
const casa = o.house || 'nyx5.com';
|
|
125
|
+
const r = new Resolver({ hosts: loadHosts() });
|
|
126
|
+
const dc = await r.domainCard(casa);
|
|
127
|
+
const res = await fetch(`${dc._estafeta}/tareas`);
|
|
128
|
+
const j = await res.json();
|
|
129
|
+
if (!res.ok) throw new Error(j.reason || `HTTP ${res.status}`);
|
|
130
|
+
if (o.json) { print(j); break; }
|
|
131
|
+
console.log(`Trabajo sembrado en ${casa} (mostrador ${j.mostrador}, árbitro ${j.arbitro}):`);
|
|
132
|
+
for (const t of j.tareas) console.log(` ${t.id} ${t.price} tok ${t.concept}\n se comprueba con: ${t.verify.map((v) => v.type).join(', ')}`);
|
|
133
|
+
console.log(`\nPara tomar una: npx @nyx5/nyx5 tomar --agent <tu-llave> --id <tarea>`);
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
case 'tomar': {
|
|
137
|
+
const a = await loadAgent();
|
|
138
|
+
const dc = await a.resolver.domainCard(o.house || a.domain);
|
|
139
|
+
const j = await (await fetch(`${dc._estafeta}/tareas`)).json();
|
|
140
|
+
const t = (j.tareas || []).find((x) => x.id === need('id'));
|
|
141
|
+
if (!t) throw new Error(`no hay una tarea con id ${o.id}. Disponibles: ${(j.tareas || []).map((x) => x.id).join(', ') || '(ninguna)'}`);
|
|
142
|
+
// Se copian los términos publicados TAL CUAL: la casa compara contra su catálogo y
|
|
143
|
+
// rechaza cualquier diferencia, así que aquí no hay nada que ajustar.
|
|
144
|
+
const enviada = await a.quote({ to: j.mostrador, contract: 'escrow', price: t.price, concept: t.concept, arbiter: j.arbitro, terms: t.terms });
|
|
145
|
+
console.log(`Cotización enviada por "${t.concept}" (${t.price} tok).`);
|
|
146
|
+
console.log('Si hay cupo, la casa retiene los tokens y te llega el contrato al buzón.');
|
|
147
|
+
console.log(` ver buzón: npx @nyx5/nyx5 inbox --agent ${o.agent}`);
|
|
148
|
+
console.log(` al terminar: npx @nyx5/nyx5 libro --agent ${o.agent} --op deliver --args '{"contract":"<id>"}'`);
|
|
149
|
+
if (o.json) print(enviada);
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
// ----- El humano fija tope y ámbito UNA vez; dentro de eso el agente contrata solo -----
|
|
153
|
+
case 'mandate': {
|
|
154
|
+
const a = await loadAgent();
|
|
155
|
+
const r = await mandate(a, {
|
|
156
|
+
grantee: need('grantee'), cap: need('cap'),
|
|
157
|
+
scope: o.scope ? JSON.parse(o.scope) : null, expires: o.expires || null, house: o.house || null,
|
|
158
|
+
});
|
|
159
|
+
if (o.json || !r.mandate) { print(r); break; }
|
|
160
|
+
const m = r.mandate;
|
|
161
|
+
console.log(`Mandato ${m.id} creado.`);
|
|
162
|
+
console.log(` ${m.grantee} puede gastar hasta ${m.cap} tokens de la cuenta de ${m.grantor}.`);
|
|
163
|
+
if (m.expires) console.log(` Vence: ${m.expires}`);
|
|
164
|
+
if (Object.keys(m.scope || {}).length) console.log(` Ámbito: ${JSON.stringify(m.scope)}`);
|
|
165
|
+
console.log(` Revocar en cualquier momento: npx @nyx5/nyx5 libro --agent <tu-llave> --op revoke --args '{"mandate":"${m.id}"}'`);
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
// ----- Reputación = una consulta al libro (pública) -----
|
|
169
|
+
case 'historial': {
|
|
170
|
+
if (o.address && !o.agent) {
|
|
171
|
+
const { local, domain } = (await import('../src/correo/resolver.js')).parseAddress(o.address);
|
|
172
|
+
const r = new Resolver({ hosts: loadHosts() });
|
|
173
|
+
const dc = await r.domainCard(domain);
|
|
174
|
+
const res = await fetch(`${dc._estafeta}/agents/${encodeURIComponent(local)}/historial`);
|
|
175
|
+
const j = await res.json();
|
|
176
|
+
if (!res.ok) throw new Error(j.reason || `HTTP ${res.status}`);
|
|
177
|
+
print(j); break;
|
|
178
|
+
}
|
|
179
|
+
const a = await loadAgent();
|
|
180
|
+
print(await a.historial(o.address || a.address)); break;
|
|
181
|
+
}
|
|
62
182
|
case 'estafeta': {
|
|
63
183
|
const e = new Estafeta({
|
|
64
184
|
domain: need('domain'), port: Number(o.port || 4000), dataDir: need('data'),
|
|
65
|
-
adminToken: o['admin-token'] || process.env.CHASQUI_ADMIN_TOKEN || need('admin-token'),
|
|
185
|
+
adminToken: o['admin-token'] || (process.env.NYX5_ADMIN_TOKEN || process.env.CHASQUI_ADMIN_TOKEN) || need('admin-token'),
|
|
66
186
|
publicUrl: o['public-url'], hosts: loadHosts(),
|
|
67
187
|
policy: { require_relay: !!o['require-relay'], registration: o.registration || 'admin' },
|
|
68
188
|
libro: { welcome: Number(o.welcome || 0), feePct: o.fee != null ? Number(o.fee) : null },
|
|
@@ -88,11 +208,11 @@ try {
|
|
|
88
208
|
const capabilities = {};
|
|
89
209
|
if (o.mcp) capabilities.mcp = o.mcp;
|
|
90
210
|
if (o.a2a) capabilities.a2a = o.a2a;
|
|
91
|
-
print(await a.register({ adminToken: o['admin-token'] || process.env.CHASQUI_ADMIN_TOKEN, invite: o.invite, inbox, capabilities, webhook: o.webhook }));
|
|
211
|
+
print(await a.register({ adminToken: o['admin-token'] || (process.env.NYX5_ADMIN_TOKEN || process.env.CHASQUI_ADMIN_TOKEN), invite: o.invite, inbox, capabilities, webhook: o.webhook }));
|
|
92
212
|
break;
|
|
93
213
|
}
|
|
94
214
|
case 'invite': {
|
|
95
|
-
const res = await fetch(`${need('estafeta')}/invitations`, { method: 'POST', headers: { 'content-type': 'application/json', authorization: `Bearer ${o['admin-token'] || process.env.CHASQUI_ADMIN_TOKEN}` }, body: JSON.stringify({ uses: Number(o.uses || 1), expires: o.expires || null, note: o.note || null, welcome: o.welcome != null ? Number(o.welcome) : null }) });
|
|
215
|
+
const res = await fetch(`${need('estafeta')}/invitations`, { method: 'POST', headers: { 'content-type': 'application/json', authorization: `Bearer ${o['admin-token'] || (process.env.NYX5_ADMIN_TOKEN || process.env.CHASQUI_ADMIN_TOKEN)}` }, body: JSON.stringify({ uses: Number(o.uses || 1), expires: o.expires || null, note: o.note || null, welcome: o.welcome != null ? Number(o.welcome) : null }) });
|
|
96
216
|
print(await res.json()); break;
|
|
97
217
|
}
|
|
98
218
|
case 'directory': {
|
|
@@ -146,7 +266,7 @@ try {
|
|
|
146
266
|
|
|
147
267
|
// ----- Libro -----
|
|
148
268
|
case 'topup': {
|
|
149
|
-
const res = await fetch(`${need('estafeta')}/libro/topup`, { method: 'POST', headers: { 'content-type': 'application/json', authorization: `Bearer ${o['admin-token'] || process.env.CHASQUI_ADMIN_TOKEN}` }, body: JSON.stringify({ account: need('account'), amount: Number(need('amount')), concept: o.concept }) });
|
|
269
|
+
const res = await fetch(`${need('estafeta')}/libro/topup`, { method: 'POST', headers: { 'content-type': 'application/json', authorization: `Bearer ${o['admin-token'] || (process.env.NYX5_ADMIN_TOKEN || process.env.CHASQUI_ADMIN_TOKEN)}` }, body: JSON.stringify({ account: need('account'), amount: Number(need('amount')), concept: o.concept }) });
|
|
150
270
|
print(await res.json()); break;
|
|
151
271
|
}
|
|
152
272
|
case 'balance': print(await (await loadAgent()).balance(o.house)); break;
|
|
@@ -175,7 +295,7 @@ try {
|
|
|
175
295
|
console.log(`agente delegado ${sub.address} creado; claves en ${out}`); break;
|
|
176
296
|
}
|
|
177
297
|
default:
|
|
178
|
-
console.log(fs.readFileSync(new URL(import.meta.url)).toString().split('\n').slice(1,
|
|
298
|
+
console.log(fs.readFileSync(new URL(import.meta.url)).toString().split('\n').slice(1, 33).map((l) => l.replace(/^\/\/ ?/, '')).join('\n'));
|
|
179
299
|
process.exit(cmd ? 1 : 0);
|
|
180
300
|
}
|
|
181
301
|
} catch (e) {
|
package/demo/contratos.js
CHANGED
|
@@ -11,7 +11,7 @@ import { Estafeta } from '../src/correo/estafeta.js';
|
|
|
11
11
|
import { Agent } from '../src/correo/agente.js';
|
|
12
12
|
import { sha256hex } from '../src/nucleo/crypto.js';
|
|
13
13
|
|
|
14
|
-
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), '
|
|
14
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'nyx5-libro-'));
|
|
15
15
|
const hosts = { 'alfa.local': { url: 'http://127.0.0.1:4001' }, 'beta.local': { url: 'http://127.0.0.1:4002' } };
|
|
16
16
|
const mk = (domain, port, token, libro) => new Estafeta({ domain, port, dataDir: path.join(tmp, domain), adminToken: token, hosts, workerIntervalMs: 200, libro, log: () => {} });
|
|
17
17
|
const step = (n, t) => console.log(`\n[${n}] ${t}`);
|
package/demo/e2e.js
CHANGED
|
@@ -9,7 +9,7 @@ import path from 'node:path';
|
|
|
9
9
|
import { Estafeta } from '../src/correo/estafeta.js';
|
|
10
10
|
import { Agent } from '../src/correo/agente.js';
|
|
11
11
|
|
|
12
|
-
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), '
|
|
12
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'nyx5-'));
|
|
13
13
|
const hosts = { 'alfa.local': { url: 'http://127.0.0.1:4001' }, 'beta.local': { url: 'http://127.0.0.1:4002' } };
|
|
14
14
|
const step = (n, t) => console.log(`\n[${n}] ${t}`);
|
|
15
15
|
|
package/demo/offline.js
CHANGED
|
@@ -9,7 +9,7 @@ import path from 'node:path';
|
|
|
9
9
|
import { Estafeta } from '../src/correo/estafeta.js';
|
|
10
10
|
import { Agent } from '../src/correo/agente.js';
|
|
11
11
|
|
|
12
|
-
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), '
|
|
12
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'nyx5-off-'));
|
|
13
13
|
const hosts = { 'alfa.local': { url: 'http://127.0.0.1:4001' }, 'beta.local': { url: 'http://127.0.0.1:4002' } };
|
|
14
14
|
const mk = (domain, port, token) => new Estafeta({ domain, port, dataDir: path.join(tmp, domain), adminToken: token, hosts, workerIntervalMs: 300, retry: { baseMs: 300, maxMs: 1500 }, log: () => {} });
|
|
15
15
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
package/demo/piloto-d4.mjs
CHANGED
|
@@ -21,7 +21,7 @@ import { sha256hex } from '../src/nucleo/crypto.js';
|
|
|
21
21
|
const DOM = 'pilot.local';
|
|
22
22
|
const URL = 'http://127.0.0.1:4090';
|
|
23
23
|
const hosts = { [DOM]: { url: URL } };
|
|
24
|
-
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), '
|
|
24
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'nyx5-d4-'));
|
|
25
25
|
|
|
26
26
|
// La casa: fee 20% (como b.chsq.uk en producción), sin regalo de bienvenida (el presupuesto entra por topup).
|
|
27
27
|
const casa = await new Estafeta({ domain: DOM, port: 4090, dataDir: path.join(tmp, DOM), adminToken: 'p',
|
package/demo/spam.js
CHANGED
|
@@ -10,7 +10,7 @@ import { Estafeta } from '../src/correo/estafeta.js';
|
|
|
10
10
|
import { Agent } from '../src/correo/agente.js';
|
|
11
11
|
import { generateKeys, signObject, uuid } from '../src/nucleo/crypto.js';
|
|
12
12
|
|
|
13
|
-
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), '
|
|
13
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'nyx5-spam-'));
|
|
14
14
|
const hosts = { 'alfa.local': { url: 'http://127.0.0.1:4001' }, 'beta.local': { url: 'http://127.0.0.1:4002' } };
|
|
15
15
|
const mk = (domain, port, token) => new Estafeta({ domain, port, dataDir: path.join(tmp, domain), adminToken: token, hosts, workerIntervalMs: 200, log: () => {} });
|
|
16
16
|
const step = (n, t) => console.log(`\n[${n}] ${t}`);
|