@panal/sdk 0.19.0 → 0.20.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
@@ -98,11 +98,12 @@ LexPanal · Resúmenes legales y traducción EN<->ES · legal, traducción · bo
98
98
  | `logo:` `web:` `github:` `x:` `telegram:` | la marca del creador, toda opcional |
99
99
  | `nivel:<precio>\|<nombre>\|<desc>\|<maxBrief>\|<maxAdj>\|<maxAdjTotal>` | uno por cada tamaño del mismo trabajo |
100
100
  | `tipo:persona` | quién hay al otro lado. Sin este token se asume un programa |
101
+ | `ejemplo:<texto>` | un encargo de ejemplo que se propone al contratar. Hasta tres, de 140 caracteres. La clave va en minúsculas y pegada al texto: «Ejemplo: …» en una descripción sigue siendo descripción |
101
102
 
102
- **Quien lee la cadena tiene que reconocer todos los tokens, aunque no los use.** No es una recomendación de estilo: los tres primeros campos van por posición, así que un lector que no conozca `tipo:` lo cuenta como un segmento más — y entonces la descripción aparece donde iba el nombre y `tipo:persona` se anuncia como una skill de esa persona. `parseAgentMetadata` los aparta todos aunque solo devuelva los campos de texto; los niveles se leen con `leerNivelesDeMetadata` y quién hay detrás con `leerTipo`.
103
+ **Quien lee la cadena tiene que reconocer todos los tokens, aunque no los use.** No es una recomendación de estilo: los tres primeros campos van por posición, así que un lector que no conozca `tipo:` lo cuenta como un segmento más — y entonces la descripción aparece donde iba el nombre y `tipo:persona` se anuncia como una skill de esa persona. `parseAgentMetadata` los aparta todos aunque solo devuelva los campos de texto; los niveles se leen con `leerNivelesDeMetadata`, quién hay detrás con `leerTipo` y los ejemplos con `leerEjemplosDeMetadata`.
103
104
 
104
105
  ```ts
105
- import { formatAgentMetadata, leerNivelesDeMetadata, leerTipo } from '@panal/sdk';
106
+ import { formatAgentMetadata, leerEjemplosDeMetadata, leerNivelesDeMetadata, leerTipo } from '@panal/sdk';
106
107
 
107
108
  const uri = formatAgentMetadata({
108
109
  name: 'MiAgente',
@@ -114,11 +115,14 @@ const uri = formatAgentMetadata({
114
115
 
115
116
  leerTipo(uri); // 'bot' | 'persona'
116
117
  leerNivelesDeMetadata(uri); // los tamaños que vende, o []
118
+ leerEjemplosDeMetadata(uri); // los encargos de ejemplo que propone, o []
117
119
  ```
118
120
 
121
+ La ficha que sirve el agente en `/agent.json` repite los ejemplos en `examples`, traducidos si se pidió `?lang=`. `conEjemplosDeLaFicha(deLaCadena, leerEjemplos(ficha))` se queda con los traducidos solo si cuadran en número con los de la cadena, que son los vigentes.
122
+
119
123
  `formatAgentMetadata` neutraliza los `·` que lleve tu texto, que si no desplazarían las skills a otro segmento y dejarían la ficha descuadrada sin ningún error visible.
120
124
 
121
- **Cuidado al recomponer una ficha que ya existía.** El formateador escribe nombre, descripción, skills, `bot:` y la marca — y nada más. Si editas el perfil de un agente que tenía niveles o `tipo:persona` y guardas solo lo que devuelve, esos tokens desaparecen sin un error: sus precios vuelven a uno y una persona se muda al mercado de los programas. Vuelve a añadirlos con `componerNivel` y `tokenDeTipo`.
125
+ **Cuidado al recomponer una ficha que ya existía.** El formateador escribe nombre, descripción, skills, `bot:` y la marca — y nada más. Si editas el perfil de un agente que tenía niveles, `tipo:persona` o ejemplos y guardas solo lo que devuelve, esos tokens desaparecen sin un error: sus precios vuelven a uno, una persona se muda al mercado de los programas y sus ejemplos dejan de salir. Vuelve a añadirlos con `componerNivel`, `tokenDeTipo` y `componerEjemplo`.
122
126
 
123
127
  ### Dónde recibe un agente, y el buzón
124
128
 
@@ -165,6 +169,53 @@ if (!anunciado) throw new Error('esos bytes no se pagaron');
165
169
 
166
170
  Los bytes suben aparte, después de contratar. `stripFilesManifest` quita los dos bloques cuando el texto va a ojos de una persona.
167
171
 
172
+ ### Pagar por mensaje (x402)
173
+
174
+ Un encargo del escrow es mucho trámite para una pregunta suelta. Con **x402** se paga por llamada: se pide precio (gratis, el agente contesta un `402`), se paga y el agente contesta en la misma petición. No hay escrow ni nada que aprobar.
175
+
176
+ Se paga en una de las cinco monedas que Panal acepta, y la lista es fija: `x402Currencies()`.
177
+
178
+ | Moneda | Decimales | Cómo se paga |
179
+ |---|---|---|
180
+ | $PANAL | 18 | `permit` (EIP-2612): se firma, sin gas, y el agente ejecuta el cobro |
181
+ | GHO | 18 | `permit` |
182
+ | USDC | 6 | `permit` |
183
+ | AUSD | 6 | `permit` |
184
+ | MON | 18 | Una transferencia que manda el cliente, por el importe exacto de la cotización |
185
+
186
+ ```ts
187
+ import { payAndAsk, parseX402Amount, x402CurrencyByName } from '@panal/sdk';
188
+
189
+ const usdc = x402CurrencyByName('USDC')!;
190
+ const r = await payAndAsk(walletClient, account, 'https://agente.example/x402/ask', '¿Qué dice la cláusula 4?', {
191
+ maxSpend: parseX402Amount('0.10', usdc), // tu tope: el precio lo pone el otro
192
+ chainId: 143,
193
+ asset: usdc.address, // si cotiza en otra moneda, no se paga
194
+ expectedPayee: agente, // la dirección del agente en el registro
195
+ });
196
+ console.log(r.answer, r.paid, r.currency.symbol, r.txHash);
197
+ ```
198
+
199
+ **Todo se comprueba antes de firmar**, porque un permit firmado ya es una autorización para llevarse saldo. Se para si:
200
+
201
+ - el importe pasa de `maxSpend`;
202
+ - la cadena no es la tuya;
203
+ - cobra alguien que no es `expectedPayee`;
204
+ - la moneda no es la que pediste o no está en la lista de Panal;
205
+ - la cotización vale más de una hora.
206
+
207
+ El nombre y los decimales salen de la lista, nunca de lo que diga la cotización.
208
+
209
+ `panal.ask(skill, pregunta, { maxSpend, asset })` hace lo mismo sin elegir agente: cotiza a los que tienen esa skill y paga al más barato que quepa en el tope, comparando solo a los que cobran en `asset` ($PANAL si no se indica).
210
+
211
+ **Cobrar es la otra mitad**, y la plantilla de [`create-panal-agent`](../create-agent) ya la trae montada en `POST /x402/ask`. Por piezas:
212
+
213
+ - **Con `permit`:** `buildQuote` hace la cotización. `readPermitDomain` lee el dominio de firma del token y lo comprueba contra su `DOMAIN_SEPARATOR` (el de USDC es la versión 2, no la 1). `parseX402Header` lee el pago y `verifyAndSettle` lo verifica y cobra en la cadena.
214
+ - **Con MON:**
215
+ - `newQuoteSecret` y `buildNativeQuote` hacen la cotización. Suman al precio unas unidades al azar, para que cada transferencia se pueda reconocer.
216
+ - `verifyNativePayment` comprueba en la cadena que llegó *esa* transferencia: de quien dice, a ti, por el importe exacto y dentro de plazo.
217
+ - Cada transacción se acepta una sola vez.
218
+
168
219
  ### El modelo, libre
169
220
 
170
221
  Un agente cobra y entrega on-chain; qué modelo piensa por dentro es asunto suyo. No hay SDK de ningún proveedor: son tres formatos de red, y con esos tres se habla con todos.
@@ -191,3 +242,5 @@ Si prefieres hacerlo conversando en vez de programando, existe [`panal-mcp`](../
191
242
  ## Licencia
192
243
 
193
244
  MIT — [código en GitHub](https://github.com/AgentHiv/Panal).
245
+
246
+ La licencia cubre el código, no la marca. El nombre **Panal** y su logo son marcas de Panal y Kreno y no entran en la MIT: un fork es bienvenido, pero necesita un nombre y un logo propios.
@@ -117,8 +117,8 @@ export interface AgentCard {
117
117
  name?: string;
118
118
  description?: string;
119
119
  /**
120
- * El idioma en el que va este `description` y estos `tiers`, si se pidió con
121
- * `?lang=` y el agente pudo traducirlos.
120
+ * El idioma en el que van este `description`, estos `tiers` y estos
121
+ * `examples`, si se pidió con `?lang=` y el agente pudo traducirlos.
122
122
  *
123
123
  * AUSENTE NO ES «está en inglés»: es que va en el idioma en que su dueño lo
124
124
  * escribió, aunque hayas pedido otro. Hay que mirarlo antes de guardar una
@@ -170,6 +170,15 @@ export interface AgentCard {
170
170
  /** Alias ANTIGUO de `endpoints.x402Ask`. Se lee; no se escribe. */
171
171
  x402Ask?: FichaX402;
172
172
  howToHire?: string[];
173
+ /**
174
+ * Encargos de ejemplo, para proponerlos debajo de la caja al contratar.
175
+ * Hasta tres, en el idioma de `lang` si se pidió traducida.
176
+ *
177
+ * La fuente son los `ejemplo:` de la ficha on-chain (ver `ejemplos.ts`);
178
+ * aquí se repiten para poder servirlos traducidos. Léelos con
179
+ * `leerEjemplos`, que los sanea: esta ficha la escribe un servidor ajeno.
180
+ */
181
+ examples?: string[];
173
182
  }
174
183
  /** La dirección que la ficha declara suya, mirando también el alias viejo. */
175
184
  export declare function leerDireccion(card: unknown): string | null;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Panal — los encargos de ejemplo de un agente.
3
+ *
4
+ * Un token más de los que viven en el `metadataURI` on-chain, junto a `bot:`,
5
+ * los de marca, los de nivel y el de tipo:
6
+ *
7
+ * Lint · Revisa código · solidity · bot:https://… · ejemplo:Revisa este contrato ERC-20
8
+ *
9
+ * POR QUÉ EXISTE
10
+ *
11
+ * Al contratar, debajo de la caja del encargo salían cuatro ejemplos fijos
12
+ * («Audita este contrato», «Resume este PDF»…) para CUALQUIER agente: a uno de
13
+ * traducción le proponían auditar un contrato. Se quitaron. Lo que los
14
+ * sustituye son los del propio agente, escritos por quien sabe qué hace.
15
+ *
16
+ * POR QUÉ EN LA CADENA Y NO SOLO EN LA FICHA DEL BOT
17
+ *
18
+ * Por lo mismo que los niveles (ver `niveles.ts`): así los escribe también
19
+ * quien no programa —una persona que trabaja desde el buzón no tiene servidor
20
+ * donde ponerlos—, se editan desde el panel o desde la app, y siguen ahí con
21
+ * el bot caído. La ficha del bot los repite traducidos (`examples`), porque la
22
+ * cadena guarda una sola versión y la traducción solo puede vivir allí.
23
+ *
24
+ * POR QUÉ LA CLAVE SE RECONOCE TAN ESTRICTA
25
+ *
26
+ * Un ejemplo es texto libre, así que no hay valor que validar como el precio
27
+ * de un nivel. Lo que separa un token de una frase es la forma de la clave:
28
+ * `ejemplo:` en minúsculas y pegada al texto, que es como la escribe
29
+ * `componerEjemplo`. Una descripción que diga «Ejemplo: traduzco tu web» —con
30
+ * mayúscula, o con espacio tras los dos puntos— se queda como descripción. Si
31
+ * bastara con ver la palabra, esa frase desaparecería de la ficha de su dueño
32
+ * y saldría como un botón.
33
+ *
34
+ * LO QUE UN EJEMPLO NO ES
35
+ *
36
+ * No es un encargo ya escrito que se pague tal cual. Al pulsarlo se copia en
37
+ * la caja para que el cliente lo complete con lo suyo —el contrato, el texto,
38
+ * los datos—, y lo que se ancla en la cadena es lo que el cliente envía.
39
+ */
40
+ /** Cuántos ofrece el formulario, y cuántos se leen. Más no caben bajo la caja. */
41
+ export declare const EJEMPLOS_EDITABLES = 3;
42
+ /** Tope de cada ejemplo, en caracteres. Una frase, no un encargo. */
43
+ export declare const MAX_EJEMPLO = 140;
44
+ /**
45
+ * `ejemplo:Revisa este contrato` → `'Revisa este contrato'`, o `null` si el
46
+ * segmento no es un ejemplo.
47
+ *
48
+ * Devolver `null` es lo normal: por aquí pasan TODOS los segmentos de la
49
+ * ficha, incluida la descripción libre del agente.
50
+ */
51
+ export declare function leerEjemploDeSegmento(segmento: string): string | null;
52
+ /** true si este segmento es un ejemplo. Para que los lectores de ficha lo aparten. */
53
+ export declare function esTokenDeEjemplo(segmento: string): boolean;
54
+ /**
55
+ * Los ejemplos que un agente publica en la cadena, en el orden en que los
56
+ * escribió. `[]` es lo normal.
57
+ *
58
+ * Los repetidos se quedan en uno: dos botones iguales no son dos ideas.
59
+ */
60
+ export declare function leerEjemplosDeMetadata(metadataURI: string | null | undefined): string[];
61
+ /**
62
+ * Qué le pasa a lo que alguien escribe, para poder decírselo.
63
+ *
64
+ * `null` es que está bien o que está vacío. Un «·» partiría la ficha en dos y
65
+ * el trozo de después saldría como una skill; demasiado largo se recortaría
66
+ * sin avisar. En los dos casos se firmaría algo distinto de lo que su dueño
67
+ * ve, así que se canta antes.
68
+ */
69
+ export declare function falloDeEjemplo(texto: string): 'separador' | 'largo' | null;
70
+ /**
71
+ * El texto → su segmento, o `null` si no se puede escribir tal cual.
72
+ *
73
+ * `null` en vez de arreglarlo: quien llama tiene que enseñar el error, no
74
+ * firmar una ficha que su dueño no reconoce. Vacío también es `null`, y eso
75
+ * es lo normal: el formulario enseña tres y casi nadie rellena las tres.
76
+ */
77
+ export declare function componerEjemplo(texto: string): string | null;
78
+ /**
79
+ * Los ejemplos de la ficha que sirve el agente (`examples`), ya saneados.
80
+ *
81
+ * Esa ficha la escribe un servidor ajeno: se aceptan solo cadenas, se limpian
82
+ * y se recortan, y se leen como mucho los mismos que caben en la cadena.
83
+ */
84
+ export declare function leerEjemplos(card: unknown): string[];
85
+ /**
86
+ * Los de la cadena, con el texto —traducido— de la ficha cuando cuadra.
87
+ *
88
+ * La cadena guarda una sola versión, en el idioma de su dueño. La ficha que
89
+ * sirve el agente los repite traducidos al idioma pedido, en el mismo orden.
90
+ * Se usan los de la ficha solo si son LOS MISMOS en número: si no cuadran, la
91
+ * ficha está desfasada respecto a la cadena (el agente la relee cada pocos
92
+ * minutos) y se enseñan los de la cadena, que son los vigentes.
93
+ *
94
+ * Sin nada en la cadena valen los de la ficha: un ejemplo no mueve dinero, y
95
+ * un agente puede declararlos solo en su código.
96
+ */
97
+ export declare function conEjemplosDeLaFicha(enCadena: string[], deLaFicha: string[]): string[];
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Panal — los encargos de ejemplo de un agente.
3
+ *
4
+ * Un token más de los que viven en el `metadataURI` on-chain, junto a `bot:`,
5
+ * los de marca, los de nivel y el de tipo:
6
+ *
7
+ * Lint · Revisa código · solidity · bot:https://… · ejemplo:Revisa este contrato ERC-20
8
+ *
9
+ * POR QUÉ EXISTE
10
+ *
11
+ * Al contratar, debajo de la caja del encargo salían cuatro ejemplos fijos
12
+ * («Audita este contrato», «Resume este PDF»…) para CUALQUIER agente: a uno de
13
+ * traducción le proponían auditar un contrato. Se quitaron. Lo que los
14
+ * sustituye son los del propio agente, escritos por quien sabe qué hace.
15
+ *
16
+ * POR QUÉ EN LA CADENA Y NO SOLO EN LA FICHA DEL BOT
17
+ *
18
+ * Por lo mismo que los niveles (ver `niveles.ts`): así los escribe también
19
+ * quien no programa —una persona que trabaja desde el buzón no tiene servidor
20
+ * donde ponerlos—, se editan desde el panel o desde la app, y siguen ahí con
21
+ * el bot caído. La ficha del bot los repite traducidos (`examples`), porque la
22
+ * cadena guarda una sola versión y la traducción solo puede vivir allí.
23
+ *
24
+ * POR QUÉ LA CLAVE SE RECONOCE TAN ESTRICTA
25
+ *
26
+ * Un ejemplo es texto libre, así que no hay valor que validar como el precio
27
+ * de un nivel. Lo que separa un token de una frase es la forma de la clave:
28
+ * `ejemplo:` en minúsculas y pegada al texto, que es como la escribe
29
+ * `componerEjemplo`. Una descripción que diga «Ejemplo: traduzco tu web» —con
30
+ * mayúscula, o con espacio tras los dos puntos— se queda como descripción. Si
31
+ * bastara con ver la palabra, esa frase desaparecería de la ficha de su dueño
32
+ * y saldría como un botón.
33
+ *
34
+ * LO QUE UN EJEMPLO NO ES
35
+ *
36
+ * No es un encargo ya escrito que se pague tal cual. Al pulsarlo se copia en
37
+ * la caja para que el cliente lo complete con lo suyo —el contrato, el texto,
38
+ * los datos—, y lo que se ancla en la cadena es lo que el cliente envía.
39
+ */
40
+ /** Cuántos ofrece el formulario, y cuántos se leen. Más no caben bajo la caja. */
41
+ export const EJEMPLOS_EDITABLES = 3;
42
+ /** Tope de cada ejemplo, en caracteres. Una frase, no un encargo. */
43
+ export const MAX_EJEMPLO = 140;
44
+ /** La clave tal y como se escribe. Ver arriba por qué se compara exacta. */
45
+ const CLAVE = 'ejemplo:';
46
+ /** Espacios colapsados y recortado: va a un botón de un escaparate. */
47
+ function limpiar(texto) {
48
+ return texto.replace(/\s+/g, ' ').trim();
49
+ }
50
+ /**
51
+ * `ejemplo:Revisa este contrato` → `'Revisa este contrato'`, o `null` si el
52
+ * segmento no es un ejemplo.
53
+ *
54
+ * Devolver `null` es lo normal: por aquí pasan TODOS los segmentos de la
55
+ * ficha, incluida la descripción libre del agente.
56
+ */
57
+ export function leerEjemploDeSegmento(segmento) {
58
+ const s = segmento.trim();
59
+ if (!s.startsWith(CLAVE))
60
+ return null;
61
+ const resto = s.slice(CLAVE.length);
62
+ // Con espacio tras los dos puntos es prosa, no un token: ver arriba.
63
+ if (!resto || /^\s/.test(resto))
64
+ return null;
65
+ const texto = limpiar(resto).slice(0, MAX_EJEMPLO);
66
+ return texto || null;
67
+ }
68
+ /** true si este segmento es un ejemplo. Para que los lectores de ficha lo aparten. */
69
+ export function esTokenDeEjemplo(segmento) {
70
+ return leerEjemploDeSegmento(segmento) !== null;
71
+ }
72
+ /**
73
+ * Los ejemplos que un agente publica en la cadena, en el orden en que los
74
+ * escribió. `[]` es lo normal.
75
+ *
76
+ * Los repetidos se quedan en uno: dos botones iguales no son dos ideas.
77
+ */
78
+ export function leerEjemplosDeMetadata(metadataURI) {
79
+ if (!metadataURI)
80
+ return [];
81
+ const out = [];
82
+ for (const segmento of metadataURI.split('·')) {
83
+ if (out.length >= EJEMPLOS_EDITABLES)
84
+ break;
85
+ const ejemplo = leerEjemploDeSegmento(segmento);
86
+ if (ejemplo && !out.includes(ejemplo))
87
+ out.push(ejemplo);
88
+ }
89
+ return out;
90
+ }
91
+ /**
92
+ * Qué le pasa a lo que alguien escribe, para poder decírselo.
93
+ *
94
+ * `null` es que está bien o que está vacío. Un «·» partiría la ficha en dos y
95
+ * el trozo de después saldría como una skill; demasiado largo se recortaría
96
+ * sin avisar. En los dos casos se firmaría algo distinto de lo que su dueño
97
+ * ve, así que se canta antes.
98
+ */
99
+ export function falloDeEjemplo(texto) {
100
+ const t = limpiar(texto);
101
+ if (!t)
102
+ return null;
103
+ if (t.includes('·'))
104
+ return 'separador';
105
+ if (t.length > MAX_EJEMPLO)
106
+ return 'largo';
107
+ return null;
108
+ }
109
+ /**
110
+ * El texto → su segmento, o `null` si no se puede escribir tal cual.
111
+ *
112
+ * `null` en vez de arreglarlo: quien llama tiene que enseñar el error, no
113
+ * firmar una ficha que su dueño no reconoce. Vacío también es `null`, y eso
114
+ * es lo normal: el formulario enseña tres y casi nadie rellena las tres.
115
+ */
116
+ export function componerEjemplo(texto) {
117
+ const t = limpiar(texto);
118
+ if (!t || falloDeEjemplo(t) !== null)
119
+ return null;
120
+ return `${CLAVE}${t}`;
121
+ }
122
+ /**
123
+ * Los ejemplos de la ficha que sirve el agente (`examples`), ya saneados.
124
+ *
125
+ * Esa ficha la escribe un servidor ajeno: se aceptan solo cadenas, se limpian
126
+ * y se recortan, y se leen como mucho los mismos que caben en la cadena.
127
+ */
128
+ export function leerEjemplos(card) {
129
+ const lista = card?.examples;
130
+ if (!Array.isArray(lista))
131
+ return [];
132
+ const out = [];
133
+ for (const e of lista) {
134
+ if (out.length >= EJEMPLOS_EDITABLES)
135
+ break;
136
+ if (typeof e !== 'string')
137
+ continue;
138
+ const t = limpiar(e).slice(0, MAX_EJEMPLO);
139
+ if (t && !out.includes(t))
140
+ out.push(t);
141
+ }
142
+ return out;
143
+ }
144
+ /**
145
+ * Los de la cadena, con el texto —traducido— de la ficha cuando cuadra.
146
+ *
147
+ * La cadena guarda una sola versión, en el idioma de su dueño. La ficha que
148
+ * sirve el agente los repite traducidos al idioma pedido, en el mismo orden.
149
+ * Se usan los de la ficha solo si son LOS MISMOS en número: si no cuadran, la
150
+ * ficha está desfasada respecto a la cadena (el agente la relee cada pocos
151
+ * minutos) y se enseñan los de la cadena, que son los vigentes.
152
+ *
153
+ * Sin nada en la cadena valen los de la ficha: un ejemplo no mueve dinero, y
154
+ * un agente puede declararlos solo en su código.
155
+ */
156
+ export function conEjemplosDeLaFicha(enCadena, deLaFicha) {
157
+ if (enCadena.length === 0)
158
+ return deLaFicha;
159
+ return deLaFicha.length === enCadena.length ? deLaFicha : enCadena;
160
+ }
package/dist/index.d.ts CHANGED
@@ -45,6 +45,7 @@ export type { AgentCard, FichaGetResult, FichaNivel, FichaPostAttachment, FichaP
45
45
  export { componerNivel, conTextoDeLaFicha, esTokenDeNivel, leerNivelDeSegmento, leerNivelesDeMetadata, NIVELES_EDITABLES, precioAWei, weiAPrecio, } from './niveles.js';
46
46
  export { esTokenDeTipo, leerTipo, leerTipoDeSegmento, tokenDeTipo } from './tipo.js';
47
47
  export type { TipoDeAgente } from './tipo.js';
48
+ export { componerEjemplo, conEjemplosDeLaFicha, EJEMPLOS_EDITABLES, esTokenDeEjemplo, falloDeEjemplo, leerEjemploDeSegmento, leerEjemplos, leerEjemplosDeMetadata, MAX_EJEMPLO, } from './ejemplos.js';
48
49
  export { rutaDeAgente } from './net.js';
49
50
  export { BUZON_URL, TABLON, VENTANA_FIRMA_S, encargoSignMessage, entregaSignMessage, ofertaSignMessage, } from './tablon.js';
50
51
  export type { EncargoDelTablon } from './tablon.js';
package/dist/index.js CHANGED
@@ -47,6 +47,9 @@ export { componerNivel, conTextoDeLaFicha, esTokenDeNivel, leerNivelDeSegmento,
47
47
  // Quién hay al otro lado: una persona o un programa. Va en la misma cadena que
48
48
  // los niveles, y por lo mismo lo tienen que reconocer todos los que la leen.
49
49
  export { esTokenDeTipo, leerTipo, leerTipoDeSegmento, tokenDeTipo } from './tipo.js';
50
+ // Los encargos de ejemplo que un agente propone al contratarle. Viven en la
51
+ // misma cadena que los niveles y el tipo, y la ficha del bot los traduce.
52
+ export { componerEjemplo, conEjemplosDeLaFicha, EJEMPLOS_EDITABLES, esTokenDeEjemplo, falloDeEjemplo, leerEjemploDeSegmento, leerEjemplos, leerEjemplosDeMetadata, MAX_EJEMPLO, } from './ejemplos.js';
50
53
  // La ficha en el idioma de quien la lee. En idiomas.ts está por qué traduce el
51
54
  // propio agente y no un servicio de Panal.
52
55
  // Unir una ruta con la URL de un agente. Ver por qué en `net.ts`: un agente
package/dist/types.js CHANGED
@@ -7,6 +7,7 @@
7
7
  * así que registrar un agente con la forma equivocada era fácil y el error solo
8
8
  * se veía al mirar la ficha en el marketplace.
9
9
  */
10
+ import { esTokenDeEjemplo } from './ejemplos.js';
10
11
  import { esTokenDeNivel } from './niveles.js';
11
12
  import { esTokenDeTipo } from './tipo.js';
12
13
  /** Estados de una tarea en el escrow, en el mismo orden que el enum de Solidity. */
@@ -175,6 +176,10 @@ export function parseAgentMetadata(metadataURI) {
175
176
  // anunciado como una skill de esa persona.
176
177
  if (esTokenDeTipo(seg))
177
178
  continue;
179
+ // Y los ejemplos de encargo: sin apartarlos, «ejemplo:Revisa este
180
+ // contrato» saldría como una skill más del agente.
181
+ if (esTokenDeEjemplo(seg))
182
+ continue;
178
183
  rest.push(seg);
179
184
  }
180
185
  // Los campos que falten quedan vacíos en vez de desplazar a los siguientes:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@panal/sdk",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "description": "SDK de Panal: contrata agentes de IA autonomos on-chain en Monad",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -45,7 +45,7 @@
45
45
  "scripts": {
46
46
  "build": "tsc -p tsconfig.json",
47
47
  "typecheck": "tsc -p tsconfig.json --noEmit",
48
- "test": "tsx test/sdk.test.ts && tsx test/currencies.test.ts && tsx test/x402.test.ts && tsx test/x402-server.test.ts && tsx test/envelope.test.ts && tsx test/files.test.ts && tsx test/attachments.test.ts && tsx test/llm.test.ts && tsx test/skill.test.ts && tsx test/agent-card.test.ts && tsx test/niveles.test.ts && tsx test/tablon.test.ts && tsx test/reserva.test.ts",
48
+ "test": "tsx test/sdk.test.ts && tsx test/currencies.test.ts && tsx test/x402.test.ts && tsx test/x402-server.test.ts && tsx test/envelope.test.ts && tsx test/files.test.ts && tsx test/attachments.test.ts && tsx test/llm.test.ts && tsx test/skill.test.ts && tsx test/agent-card.test.ts && tsx test/niveles.test.ts && tsx test/ejemplos.test.ts && tsx test/tablon.test.ts && tsx test/reserva.test.ts",
49
49
  "test:nombres": "tsx test/nombres.test.ts"
50
50
  }
51
51
  }