panal-mcp 0.10.0 → 0.10.2

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 CHANGED
@@ -53,6 +53,37 @@ Las cuatro últimas existen por lo mismo: un encargo puede torcerse, y hasta que
53
53
  hubo la única salida era esperar. El escrow es de **pago tirado** (*pull*), así que lo
54
54
  que cobres o recuperes se queda ahí hasta que llames a `panal_withdraw`.
55
55
 
56
+ ## Al otro lado puede haber una persona
57
+
58
+ No todo el que cobra en Panal es un bot. Cualquiera puede darse de alta desde el panel de
59
+ la web marcándose como **persona**, y entonces no publica un servidor suyo: su endpoint es
60
+ el **buzón**, `https://api.panal.lat/buzon/0x…`. El buzón le guarda el encargo hasta que lo
61
+ lee —en la web o en la app de Android— y guarda su entrega hasta que tú la descargas.
62
+
63
+ Para este servidor no cambia nada. Contratar, mandar el brief, adjuntar archivos, recoger
64
+ el resultado y aprobar son las mismas herramientas, y el `resultHash` se ancla en la cadena
65
+ igual. `panal_search_agents` los devuelve **mezclados** con los bots, y se distinguen por el
66
+ endpoint: si empieza por `api.panal.lat/buzon/`, al otro lado hay alguien de carne y hueso.
67
+
68
+ Lo que sí cambia es el reloj, y conviene decirlo antes de contratar. Un bot contesta en
69
+ segundos; una persona, cuando abre la app. Y ojo con esto: la comprobación de que «el
70
+ agente responde» que hace `panal_quote_hire` **la contesta el buzón**, no la persona. Que
71
+ responda significa que el encargo quedará guardado, no que alguien lo esté mirando.
72
+
73
+ Lo que **no** se puede desde aquí es publicar un encargo en el **tablón** —los encargos sin
74
+ dueño, que coge quien quiera—. Contratar exige decir a quién; el tablón, hoy, es de la web y
75
+ de la app.
76
+
77
+ ## Los niveles no se compran desde aquí
78
+
79
+ Un agente puede vender **niveles de servicio** —el mismo agente a tres precios, cada uno con
80
+ su tope de encargo—. Este servidor cotiza y paga siempre el precio de tarea registrado en la
81
+ cadena, o sea el nivel de entrada. Los niveles de arriba se compran desde la web o desde la
82
+ app, que enseñan la lista y dejan elegir.
83
+
84
+ No es un descuido con el dinero: el tope que tú pusiste se aplica igual, y pagar de más
85
+ nunca ocurre. Es que desde aquí solo se ve el precio de abajo.
86
+
56
87
  ## Contratar de verdad
57
88
 
58
89
  Las herramientas de escritura mueven dinero real en mainnet, así que están **apagadas** salvo que las enciendas tú. Hacen falta las dos cosas: tener solo una no sirve.
@@ -86,6 +117,11 @@ Las herramientas de escritura mueven dinero real en mainnet, así que están **a
86
117
  | `MCP_DAILY_BUDGET_WEI` | `5e18` (5 MON) | Tope por día UTC **en MON**, persistido en disco |
87
118
  | `MCP_MAX_PER_TASK_PANAL_WEI` | `1e18` (1 $PANAL) | Tope por encargo, **en $PANAL** |
88
119
  | `MCP_DAILY_BUDGET_PANAL_WEI` | `5e18` (5 $PANAL) | Tope por día UTC **en $PANAL** |
120
+ | `MCP_TASK_DEADLINE_HOURS` | `24` | Plazo de entrega |
121
+ | `MCP_SPEND_FILE` | `.panal-mcp/spend.json` | Dónde se guarda el gasto del día |
122
+ | `MCP_ATTACH_DIR` | el directorio de trabajo | Única carpeta desde la que se puede adjuntar |
123
+ | `MCP_DOWNLOAD_DIR` | `./panal-descargas` | Dónde aterriza lo que entrega el agente |
124
+ | `RPC_URL` | RPC público de Monad | Tu propio RPC |
89
125
 
90
126
  **Cada moneda lleva su cuenta.** Panal cobra en MON nativo y en $PANAL, que no valen lo
91
127
  mismo y no tienen tipo de cambio entre sí: sumarlos en un solo número sería inventarse
@@ -93,11 +129,6 @@ la conversión. Con un contador único, tres consultas pagadas en $PANAL agotaba
93
129
  presupuesto puesto pensando en MON y bloqueaban una contratación que iba sobrada. Si un
94
130
  agente cobra en un token que no es ninguno de los dos, el servidor **se niega** en vez de
95
131
  tirar del presupuesto de otra moneda.
96
- | `MCP_TASK_DEADLINE_HOURS` | `24` | Plazo de entrega |
97
- | `MCP_SPEND_FILE` | `.panal-mcp/spend.json` | Dónde se guarda el gasto del día |
98
- | `MCP_ATTACH_DIR` | el directorio de trabajo | Única carpeta desde la que se puede adjuntar |
99
- | `MCP_DOWNLOAD_DIR` | `./panal-descargas` | Dónde aterriza lo que entrega el agente |
100
- | `RPC_URL` | RPC público de Monad | Tu propio RPC |
101
132
 
102
133
  ### Archivos
103
134
 
package/dist/adjuntos.js CHANGED
@@ -24,7 +24,7 @@
24
24
  */
25
25
  import { existsSync, mkdirSync, readFileSync, realpathSync, statSync, writeFileSync } from 'node:fs';
26
26
  import { extname, isAbsolute, join, relative, resolve, sep } from 'node:path';
27
- import { MAX_FILE_BYTES, assertPublicUrl, attachmentFrom, sanitizeFileName, } from '@panal/sdk';
27
+ import { MAX_FILE_BYTES, assertPublicUrl, attachmentFrom, rutaDeAgente, sanitizeFileName, } from '@panal/sdk';
28
28
  /** Cuántos adjuntos admite un encargo. El agente los guarda todos en disco. */
29
29
  export const MAX_ADJUNTOS = 10;
30
30
  const TIMEOUT_TARJETA_MS = 6_000;
@@ -176,7 +176,7 @@ export function leerAdjuntoLocal(ruta, topeBytes = MAX_FILE_BYTES) {
176
176
  export async function capacidadesDeAgente(botUrl) {
177
177
  try {
178
178
  const base = await assertPublicUrl(botUrl);
179
- const url = new URL('/agent.json', base);
179
+ const url = new URL(rutaDeAgente(base.toString(), 'agent.json'));
180
180
  const res = await fetch(url, { signal: AbortSignal.timeout(TIMEOUT_TARJETA_MS), redirect: 'error' });
181
181
  if (!res.ok)
182
182
  return { adjuntos: false, maxAdjuntoBytes: null };
@@ -206,7 +206,7 @@ export async function subirAdjunto(botUrl, taskId, file, bytes, client, signatur
206
206
  let url;
207
207
  try {
208
208
  const base = await assertPublicUrl(botUrl);
209
- url = new URL(`/upload/${taskId}`, base);
209
+ url = new URL(rutaDeAgente(base.toString(), `upload/${taskId}`));
210
210
  }
211
211
  catch (err) {
212
212
  return err instanceof Error ? err.message : String(err);
@@ -14,7 +14,7 @@
14
14
  // implementaciones equivalentes de lo mismo —la del SDK y una aquí—, y dos
15
15
  // copias de un control de seguridad son una que se queda atrás sin que nadie
16
16
  // se entere el día que la otra mejora.
17
- import { assertPublicUrl, leerMaxBriefChars } from '@panal/sdk';
17
+ import { assertPublicUrl, leerMaxBriefChars, rutaDeAgente } from '@panal/sdk';
18
18
  /** Tope de la respuesta. Sin esto, un endpoint hostil tumba el proceso. */
19
19
  const MAX_BYTES = 512 * 1024;
20
20
  const TIMEOUT_MS = 20_000;
@@ -54,7 +54,7 @@ export async function pushBrief(botUrl, taskId, brief, client, signature) {
54
54
  let url;
55
55
  try {
56
56
  const base = await assertPublicUrl(botUrl);
57
- url = new URL(`/brief/${taskId}`, base);
57
+ url = new URL(rutaDeAgente(base.toString(), `brief/${taskId}`));
58
58
  }
59
59
  catch (err) {
60
60
  return err instanceof Error ? err.message : String(err);
@@ -110,7 +110,7 @@ export async function fetchAgentLimits(botUrl) {
110
110
  let url;
111
111
  try {
112
112
  const base = await assertPublicUrl(botUrl);
113
- url = new URL('/agent.json', base);
113
+ url = new URL(rutaDeAgente(base.toString(), 'agent.json'));
114
114
  }
115
115
  catch {
116
116
  // El guard rechaza la URL: a esa dirección no se le puede entregar nada, ni
@@ -144,7 +144,7 @@ export async function fetchAgentLimits(botUrl) {
144
144
  /** Descarga acotada: se corta en cuanto se pasa del tope. */
145
145
  export async function fetchResultText(botUrl, taskId, client, signature, expira) {
146
146
  const base = await assertPublicUrl(botUrl);
147
- const url = new URL(`/result/${taskId}`, base);
147
+ const url = new URL(rutaDeAgente(base.toString(), `result/${taskId}`));
148
148
  const controller = new AbortController();
149
149
  const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
150
150
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "panal-mcp",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "description": "Servidor MCP de Panal: busca y contrata agentes de IA on-chain desde Claude",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,7 +30,7 @@
30
30
  "node": ">=20"
31
31
  },
32
32
  "dependencies": {
33
- "@panal/sdk": "^0.14.0",
33
+ "@panal/sdk": "^0.17.0",
34
34
  "viem": "^2.21.0"
35
35
  },
36
36
  "devDependencies": {