panal-mcp 0.6.0 → 0.7.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 CHANGED
@@ -34,14 +34,23 @@ Reinicia el cliente y pregunta *«¿qué agentes hay en Panal?»*.
34
34
  | Herramienta | Qué hace |
35
35
  |---|---|
36
36
  | `panal_search_agents` | Busca agentes por skill, nombre o descripción |
37
- | `panal_get_agent` | Ficha completa: precio, skills, estado |
37
+ | `panal_get_agent` | Ficha completa: precio, skills, estado y nombre único leído de la cadena |
38
38
  | `panal_get_task` | Estado de un encargo en el escrow |
39
39
  | `panal_marketplace_stats` | Cifras del marketplace |
40
40
  | `panal_wallet` | Saldo y presupuesto restante *(escritura)* |
41
- | `panal_quote_hire` | Presupuesta un encargo sin pagar *(escritura)* |
41
+ | `panal_quote_hire` | Presupuesta un encargo sin pagar, y comprueba que el agente responde *(escritura)* |
42
42
  | `panal_hire` | Contrata y bloquea el pago *(escritura)* |
43
+ | `panal_send_brief` | Reenvía el encargo si no llegó al contratar *(escritura)* |
43
44
  | `panal_get_result` | Recoge el resultado y verifica su hash *(escritura)* |
44
45
  | `panal_approve_task` | Libera el pago y valora *(escritura)* |
46
+ | `panal_quote_ask` / `panal_ask` | Pregunta suelta a un agente, sin abrir un encargo *(escritura)* |
47
+ | `panal_cancel_task` | Recupera tu dinero si nadie empezó y venció el plazo *(escritura)* |
48
+ | `panal_open_dispute` | Abre disputa si lo entregado no vale *(escritura)* |
49
+ | `panal_withdraw` | Retira lo que el escrow te debe *(escritura)* |
50
+
51
+ Las cuatro últimas existen por lo mismo: un encargo puede torcerse, y hasta que las
52
+ hubo la única salida era esperar. El escrow es de **pago tirado** (*pull*), así que lo
53
+ que cobres o recuperes se queda ahí hasta que llames a `panal_withdraw`.
45
54
 
46
55
  ## Contratar de verdad
47
56
 
@@ -80,6 +89,8 @@ Las herramientas de escritura mueven dinero real en mainnet, así que están **a
80
89
 
81
90
  **Cotizar antes de gastar.** `panal_hire` no acepta una dirección y un importe sueltos: exige el `quote_id` de un presupuesto emitido antes, y `confirmed_by_user: true`. El precio pasa obligatoriamente por la conversación —tú lo ves— antes de que se mueva nada, y el modelo no puede inventárselo. Los presupuestos caducan a los 5 minutos y son de un solo uso, así que un reintento no contrata dos veces.
82
91
 
92
+ **Se comprueba que el encargo cabe y que hay alguien al otro lado.** `panal_quote_hire` llama al endpoint del agente antes de presupuestar: si nadie contesta, te lo dice en vez de cobrarte; y si el agente publica un `maxBriefChars` y tu texto no cabe, te lo dice también. Las dos cosas se descubrían pagando —el pago quedaba bloqueado y el agente rechazaba el encargo—, que es la peor manera posible de enterarse.
93
+
83
94
  **El tope diario sobrevive a los reinicios.** Se persiste en disco con escritura atómica. Un tope que se borra al reiniciar no es un tope.
84
95
 
85
96
  **El resultado se verifica contra la cadena.** `panal_get_result` compara el hash de lo que devuelve el agente con el anclado on-chain al entregar. Si no coincide, te avisa y te dice que no apruebes: o el agente cambió el texto después, o alguien alteró la respuesta.
@@ -10,6 +10,7 @@
10
10
  * La URL sale del metadata on-chain, o sea que la escribe un desconocido: se
11
11
  * valida antes de pedirle nada, y la respuesta se lee con un tope de tamaño.
12
12
  */
13
+ import { leerMaxBriefChars } from '@panal/sdk';
13
14
  /** Cuánto vale una firma de descarga: abre toda la entrega, así que poco. */
14
15
  export declare const VENTANA_FIRMA_S: number;
15
16
  /**
@@ -46,12 +47,16 @@ export declare function pushBrief(botUrl: string, taskId: bigint, brief: string,
46
47
  * una tarea que no puede empezar. Preguntando antes, eso se convierte en un
47
48
  * presupuesto que no se emite y no cuesta nada.
48
49
  *
49
- * `maxBriefChars: null` significa NO LO SÉ, y no «no hay límite»: los agentes
50
- * de la plantilla publican una tarjeta distinta que no declara ninguno. Quien
51
- * llame tiene que poder distinguir las dos cosas, porque tratar «no lo sé» como
52
- * «no hay tope» es volver a averiguarlo pagando.
50
+ * `maxBriefChars: null` significa NO LO SÉ, y no «no hay límite». Sigue
51
+ * pasando: los agentes desplegados antes de que la plantilla lo publicara no
52
+ * declaran ninguno. Quien llame tiene que poder distinguir las dos cosas,
53
+ * porque tratar «no lo sé» como «no hay tope» es volver a averiguarlo pagando.
54
+ *
55
+ * La lectura vive en `@panal/sdk` para que haya UNA sola definición de qué es
56
+ * una ficha válida. Se reexporta con el nombre de aquí porque el servidor MCP
57
+ * ya lo usaba así.
53
58
  */
54
- export declare function parseMaxBriefChars(card: unknown): number | null;
59
+ export declare const parseMaxBriefChars: typeof leerMaxBriefChars;
55
60
  export interface LimitesDelAgente {
56
61
  /**
57
62
  * Si contestó ALGO, aunque fuera un error.
@@ -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 } from '@panal/sdk';
17
+ import { assertPublicUrl, leerMaxBriefChars } 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;
@@ -96,19 +96,16 @@ export async function pushBrief(botUrl, taskId, brief, client, signature) {
96
96
  * una tarea que no puede empezar. Preguntando antes, eso se convierte en un
97
97
  * presupuesto que no se emite y no cuesta nada.
98
98
  *
99
- * `maxBriefChars: null` significa NO LO SÉ, y no «no hay límite»: los agentes
100
- * de la plantilla publican una tarjeta distinta que no declara ninguno. Quien
101
- * llame tiene que poder distinguir las dos cosas, porque tratar «no lo sé» como
102
- * «no hay tope» es volver a averiguarlo pagando.
99
+ * `maxBriefChars: null` significa NO LO SÉ, y no «no hay límite». Sigue
100
+ * pasando: los agentes desplegados antes de que la plantilla lo publicara no
101
+ * declaran ninguno. Quien llame tiene que poder distinguir las dos cosas,
102
+ * porque tratar «no lo sé» como «no hay tope» es volver a averiguarlo pagando.
103
+ *
104
+ * La lectura vive en `@panal/sdk` para que haya UNA sola definición de qué es
105
+ * una ficha válida. Se reexporta con el nombre de aquí porque el servidor MCP
106
+ * ya lo usaba así.
103
107
  */
104
- export function parseMaxBriefChars(card) {
105
- const max = card?.endpoints?.postBrief
106
- ?.maxBriefChars;
107
- // La tarjeta la sirve un desconocido: solo un entero positivo cuenta. Un 0 o
108
- // un negativo harían imposible cualquier encargo, y eso lo decide el agente
109
- // cambiando su tope, no mandando basura en un campo.
110
- return typeof max === 'number' && Number.isInteger(max) && max > 0 ? max : null;
111
- }
108
+ export const parseMaxBriefChars = leerMaxBriefChars;
112
109
  export async function fetchAgentLimits(botUrl) {
113
110
  let url;
114
111
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "panal-mcp",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
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.10.0",
33
+ "@panal/sdk": "^0.11.0",
34
34
  "viem": "^2.21.0"
35
35
  },
36
36
  "devDependencies": {