create-panal-agent 0.9.3 → 0.10.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 +1 -1
- package/template/_package.json +1 -1
- package/template/src/server.ts +63 -14
package/package.json
CHANGED
package/template/_package.json
CHANGED
package/template/src/server.ts
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
createPanalClient,
|
|
32
32
|
LoopDetected,
|
|
33
33
|
MAINNET_ADDRESSES,
|
|
34
|
+
monad,
|
|
34
35
|
parseEnvelope,
|
|
35
36
|
parsePaymentHeader,
|
|
36
37
|
permitNonce,
|
|
@@ -54,6 +55,21 @@ const DATA_DIR = process.env.DATA_DIR ?? './data';
|
|
|
54
55
|
/** Tope del cuerpo de una petición: sin esto, cualquiera te tumba el proceso. */
|
|
55
56
|
const MAX_BODY = 256 * 1024;
|
|
56
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Tope del encargo, en CARACTERES, y anunciado en `/agent.json`.
|
|
60
|
+
*
|
|
61
|
+
* Va en caracteres y no en bytes porque es lo que el cliente puede contar
|
|
62
|
+
* antes de pagar: el tope de cuerpo de arriba protege el proceso, pero nadie
|
|
63
|
+
* sabe cuántos kilobytes ocupa su texto. Sin un número publicado, un encargo
|
|
64
|
+
* demasiado largo se descubre PAGANDO —el pago queda bloqueado, el agente
|
|
65
|
+
* responde 400, y el cliente espera al plazo para recuperarlo.
|
|
66
|
+
*
|
|
67
|
+
* El límite real lo pone MAX_BODY; este número queda holgadamente por debajo
|
|
68
|
+
* (32k caracteres son unos 128 KB incluso en el peor caso de UTF-8) para que
|
|
69
|
+
* lo que se promete se cumpla siempre, y no solo con texto latino.
|
|
70
|
+
*/
|
|
71
|
+
const MAX_BRIEF_CHARS = 32_000;
|
|
72
|
+
|
|
57
73
|
const key = process.env.AGENT_PRIVATE_KEY?.trim();
|
|
58
74
|
if (!key || !/^0x[0-9a-fA-F]{64}$/.test(key)) {
|
|
59
75
|
console.error('Falta AGENT_PRIVATE_KEY (0x + 64 hex) en el .env. Copia .env.example y rellénalo.');
|
|
@@ -743,24 +759,47 @@ const server = createServer((req, res) => {
|
|
|
743
759
|
// LexPanal tuvo x402 funcionando y nadie lo usó, sencillamente porque no
|
|
744
760
|
// salía en su tarjeta: un cobro que nadie puede descubrir no existe.
|
|
745
761
|
if (url.pathname === '/agent.json' && req.method === 'GET') {
|
|
762
|
+
const base = process.env.PUBLIC_URL?.trim().replace(/\/+$/, '') || null;
|
|
763
|
+
const x402 =
|
|
764
|
+
X402_PRICE !== null
|
|
765
|
+
? {
|
|
766
|
+
method: 'POST' as const,
|
|
767
|
+
path: '/x402/ask',
|
|
768
|
+
...(base ? { url: `${base}/x402/ask` } : {}),
|
|
769
|
+
scheme: 'eip2612-permit',
|
|
770
|
+
asset: X402_TOKEN,
|
|
771
|
+
assetSymbol: X402_SYMBOL,
|
|
772
|
+
amount: X402_PRICE.toString(),
|
|
773
|
+
payTo: account.address,
|
|
774
|
+
howTo: 'POST {"prompt":"…"} and you get a 402 with the quote. Sign it and repeat with X-Payment.',
|
|
775
|
+
}
|
|
776
|
+
: null;
|
|
777
|
+
|
|
746
778
|
json(res, 200, {
|
|
747
779
|
agent: account.address,
|
|
748
780
|
protocol: 'panal',
|
|
749
781
|
network: 'monad-mainnet',
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
782
|
+
chainId: monad.id,
|
|
783
|
+
endpoints: {
|
|
784
|
+
base,
|
|
785
|
+
postBrief: {
|
|
786
|
+
method: 'POST',
|
|
787
|
+
path: '/brief/:taskId',
|
|
788
|
+
signMessage: 'Panal brief #<taskId> (EIP-191, firmado por el cliente de la tarea)',
|
|
789
|
+
body: `{"brief": string (máx. ${MAX_BRIEF_CHARS} chars), "address": "0x…", "signature": "0x…"}`,
|
|
790
|
+
maxBriefChars: MAX_BRIEF_CHARS,
|
|
791
|
+
},
|
|
792
|
+
getResult: {
|
|
793
|
+
method: 'GET',
|
|
794
|
+
path: '/result/:taskId',
|
|
795
|
+
signMessage: 'Panal resultado #<taskId> · <epoch> (EIP-191, cabeceras X-Panal-*)',
|
|
796
|
+
},
|
|
797
|
+
...(x402 ? { x402Ask: x402 } : {}),
|
|
798
|
+
},
|
|
799
|
+
// ALIAS ANTIGUO, en la raíz. Aquí es donde esta plantilla lo publicaba
|
|
800
|
+
// antes, y hay clientes ahí fuera que solo miran este sitio. Se sirve
|
|
801
|
+
// por compatibilidad y desaparecerá; lo que se lee es `endpoints`.
|
|
802
|
+
...(x402 ? { x402Ask: x402 } : {}),
|
|
764
803
|
});
|
|
765
804
|
return;
|
|
766
805
|
}
|
|
@@ -902,6 +941,16 @@ const server = createServer((req, res) => {
|
|
|
902
941
|
json(res, 400, { error: 'faltan taskId, brief o signature' });
|
|
903
942
|
return;
|
|
904
943
|
}
|
|
944
|
+
// El tope que anuncia /agent.json, aplicado. Se dice el número en la
|
|
945
|
+
// respuesta: el cliente ya pagó, y saber cuánto recortar es la
|
|
946
|
+
// diferencia entre reenviarlo y perder el encargo.
|
|
947
|
+
if (body.brief.length > MAX_BRIEF_CHARS) {
|
|
948
|
+
json(res, 400, {
|
|
949
|
+
error: `el encargo son ${body.brief.length} caracteres y el tope es ${MAX_BRIEF_CHARS}`,
|
|
950
|
+
maxBriefChars: MAX_BRIEF_CHARS,
|
|
951
|
+
});
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
905
954
|
const taskId = BigInt(idCrudo);
|
|
906
955
|
|
|
907
956
|
// El sobre de la cadena, si este encargo viene de otro agente. Se mira
|