bcb-br-mcp 1.3.4 → 1.4.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/README.md +60 -4
- package/dist/cambio.d.ts +72 -0
- package/dist/cambio.d.ts.map +1 -0
- package/dist/cambio.js +284 -0
- package/dist/cambio.js.map +1 -0
- package/dist/catalog.d.ts +107 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +206 -0
- package/dist/catalog.js.map +1 -0
- package/dist/focus.d.ts +134 -0
- package/dist/focus.d.ts.map +1 -0
- package/dist/focus.js +683 -0
- package/dist/focus.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -346
- package/dist/index.js.map +1 -1
- package/dist/olinda.d.ts +59 -0
- package/dist/olinda.d.ts.map +1 -0
- package/dist/olinda.js +98 -0
- package/dist/olinda.js.map +1 -0
- package/dist/register.d.ts +61 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +116 -0
- package/dist/register.js.map +1 -0
- package/dist/shared.d.ts +89 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +151 -0
- package/dist/shared.js.map +1 -0
- package/dist/tools.d.ts +8128 -280
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +232 -153
- package/dist/tools.js.map +1 -1
- package/package.json +12 -11
- package/dist/worker.d.ts +0 -20
- package/dist/worker.d.ts.map +0 -1
- package/dist/worker.js +0 -240
- package/dist/worker.js.map +0 -1
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Query economic and financial indicators such as **Selic** (interest rate), **IPC
|
|
|
18
18
|
|
|
19
19
|
> If you find this project useful, please consider giving it a [star on GitHub](https://github.com/SidneyBissoli/bcb-br-mcp). It helps others discover the project!
|
|
20
20
|
|
|
21
|
-
**Capabilities:**
|
|
21
|
+
**Capabilities:** 13 tools (skills) · 3 resources · 3 prompts — everything an MCP client needs to query the Brazilian Central Bank: SGS/BCB time series, the **Focus** market-expectations survey and **PTAX** exchange rates.
|
|
22
22
|
|
|
23
23
|
## See it in action
|
|
24
24
|
|
|
@@ -27,6 +27,9 @@ Ask your assistant, in plain Portuguese:
|
|
|
27
27
|
- *"Qual a taxa Selic atual?"* → `bcb_indicadores_atuais`
|
|
28
28
|
- *"Mostre o IPCA mês a mês em 2024."* → `bcb_serie_valores`
|
|
29
29
|
- *"Qual foi a variação do dólar nos últimos 12 meses?"* → `bcb_variacao`
|
|
30
|
+
- *"O que o mercado espera do IPCA em 2027?"* → `bcb_focus_expectativas`
|
|
31
|
+
- *"Qual a Selic esperada na próxima reunião do Copom?"* → `bcb_focus_selic`
|
|
32
|
+
- *"Qual foi a PTAX de fechamento do euro na sexta?"* → `bcb_cambio_cotacao`
|
|
30
33
|
|
|
31
34
|
The answers come live from the Brazilian Central Bank's SGS API — exact figures with provenance, not numbers guessed from training data.
|
|
32
35
|
|
|
@@ -40,6 +43,8 @@ The answers come live from the Brazilian Central Bank's SGS API — exact figure
|
|
|
40
43
|
- **Current indicators** - Latest values for key economic indicators
|
|
41
44
|
- **Variation calculation** - Percentage change between periods with statistics
|
|
42
45
|
- **Series comparison** - Compare multiple series over the same period
|
|
46
|
+
- **Focus survey** - Market expectations (mean, median, std. deviation, min, max, respondents) for IPCA, GDP, FX and more, by monthly/quarterly/annual horizon or rolling 12/24-month inflation, plus Selic by Copom meeting
|
|
47
|
+
- **PTAX exchange rates** - Official closing quotes for any currency the BCB publishes, single day or date range
|
|
43
48
|
|
|
44
49
|
## Available Tools
|
|
45
50
|
|
|
@@ -53,6 +58,11 @@ The answers come live from the Brazilian Central Bank's SGS API — exact figure
|
|
|
53
58
|
| `bcb_indicadores_atuais` | Latest values: Selic, IPCA, USD/BRL, IBC-Br |
|
|
54
59
|
| `bcb_variacao` | Calculate percentage variation between dates or last N periods |
|
|
55
60
|
| `bcb_comparar` | Compare 2 to 5 series over the same period with ranking |
|
|
61
|
+
| `bcb_focus_expectativas` | Focus survey expectations for one indicator, horizon as a parameter (monthly, quarterly, annual, rolling 12m/24m inflation); `top5` flag |
|
|
62
|
+
| `bcb_focus_selic` | Focus expectations for the Selic rate, by Copom meeting (R1/2026 form) |
|
|
63
|
+
| `bcb_focus_referencias` | Which indicators and reference dates the Focus survey actually publishes, **broken down per scope** (the five horizons plus `selic`, whose axis is the Copom meeting) — the indicator set differs by scope (9 monthly vs 26 annual) |
|
|
64
|
+
| `bcb_cambio_cotacao` | PTAX quote for a currency (USD by default), single day or date range |
|
|
65
|
+
| `bcb_cambio_moedas` | Currencies with quotes published by the BCB |
|
|
56
66
|
|
|
57
67
|
## Resources
|
|
58
68
|
|
|
@@ -85,9 +95,14 @@ Visit [bcb-br-mcp on Smithery](https://smithery.ai/servers/sidneybissoli/bcb-br-
|
|
|
85
95
|
Use the HTTP endpoint directly, no installation required:
|
|
86
96
|
|
|
87
97
|
```
|
|
88
|
-
https://bcb.sidneybissoli.
|
|
98
|
+
https://bcb.sidneybissoli.com/mcp
|
|
89
99
|
```
|
|
90
100
|
|
|
101
|
+
The legacy hostname `https://bcb.sidneybissoli.workers.dev` keeps working, and so
|
|
102
|
+
does the older `POST /` route — clients configured before the endpoint moved to
|
|
103
|
+
`/mcp` are rewritten transparently, so nothing that used to work stopped working.
|
|
104
|
+
New setups should use the URL above.
|
|
105
|
+
|
|
91
106
|
### Via npx (Claude Desktop)
|
|
92
107
|
|
|
93
108
|
Add to your Claude Desktop configuration file:
|
|
@@ -324,11 +339,26 @@ The SGS database contains over 18,000 time series. To find codes for other serie
|
|
|
324
339
|
|
|
325
340
|
### Smart Search
|
|
326
341
|
|
|
327
|
-
|
|
342
|
+
`bcb_buscar_serie` searches two layers: the curated catalog of 150+ series (which ranks first, with reviewed
|
|
343
|
+
names) and the index of the BCB Open Data Portal, with thousands of series identified by code. Terms are
|
|
344
|
+
accent- and case-insensitive, and several terms are combined with AND:
|
|
328
345
|
|
|
329
346
|
- `"inflacao"` → finds "Inflação"
|
|
330
347
|
- `"cambio"` → finds "Câmbio"
|
|
331
|
-
- `"
|
|
348
|
+
- `"ipca servicos"` → both terms must match
|
|
349
|
+
|
|
350
|
+
The portal index is served from a 24-hour cache, renewed by the first search after it expires (one request to
|
|
351
|
+
the portal, only metadata — series codes and names, never observations). Every answer carries
|
|
352
|
+
`catalogo.cobertura`: the index is **not** the whole SGS, so not finding a series here is not proof it does not
|
|
353
|
+
exist.
|
|
354
|
+
|
|
355
|
+
### Data source and licence
|
|
356
|
+
|
|
357
|
+
Data obtained from the Banco Central do Brasil (SGS / Olinda-Expectativas / PTAX), published under the
|
|
358
|
+
**Open Data Commons Open Database License (ODbL) v1.0** — https://opendatacommons.org/licenses/odbl/.
|
|
359
|
+
Exchange-rate answers pass through the BCB's own liability disclaimer verbatim; cross-currency parities are
|
|
360
|
+
**not** compiled by the BCB — they come from an information agency (Refinitiv) and are redistributed by the
|
|
361
|
+
BCB, and the tools say so.
|
|
332
362
|
|
|
333
363
|
## Development
|
|
334
364
|
|
|
@@ -379,6 +409,32 @@ This server uses the Brazilian Central Bank's public API:
|
|
|
379
409
|
|
|
380
410
|
## Changelog
|
|
381
411
|
|
|
412
|
+
### v1.4.1
|
|
413
|
+
|
|
414
|
+
- `bcb_focus_referencias`: the parameter is now `escopo`, not `horizonte`, and the
|
|
415
|
+
response array is `escopos`. The scopes are the five horizons of
|
|
416
|
+
`bcb_focus_expectativas` **plus `selic`** — and `selic` is not a horizon: its
|
|
417
|
+
axis is the Copom meeting. Each block names the `tool` that consumes it. The
|
|
418
|
+
previous name implied `selic` was a queryable horizon of
|
|
419
|
+
`bcb_focus_expectativas`, which it is not. Never published to npm under the old
|
|
420
|
+
name.
|
|
421
|
+
|
|
422
|
+
### v1.4.0
|
|
423
|
+
|
|
424
|
+
- **Three APIs under one contract, 8 tools → 13.** Focus market-expectations
|
|
425
|
+
survey (`bcb_focus_expectativas`, `bcb_focus_selic`, `bcb_focus_referencias`)
|
|
426
|
+
and PTAX exchange rates (`bcb_cambio_cotacao`, `bcb_cambio_moedas`), consolidated
|
|
427
|
+
by parameter rather than mirroring the source's ~18 OData resources.
|
|
428
|
+
- **Real search.** `bcb_buscar_serie` now queries the Open Data Portal index
|
|
429
|
+
(3,500+ series, 24-hour cache, metadata only) on top of the curated catalog, and
|
|
430
|
+
states the index's coverage instead of claiming a series does not exist.
|
|
431
|
+
- Every Focus and PTAX field name verified against the live API, including the
|
|
432
|
+
Top 5 Selic resource, which publishes its fields in a different case from the
|
|
433
|
+
other twelve.
|
|
434
|
+
- ODbL obligations shipped with the exchange-rate tools: the BCB disclaimer is
|
|
435
|
+
passed through verbatim, and non-USD parities are qualified as third-party
|
|
436
|
+
(Refinitiv) data redistributed by the BCB.
|
|
437
|
+
|
|
382
438
|
### v1.2.0
|
|
383
439
|
|
|
384
440
|
- HTTP endpoint via Cloudflare Workers (`https://bcb.sidneybissoli.workers.dev`)
|
package/dist/cambio.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PTAX — cotações de câmbio e lista de moedas.
|
|
3
|
+
*
|
|
4
|
+
* Desenho aprovado (fronteira concreta da sessão de D3): os quatro recursos de
|
|
5
|
+
* cotação da fonte (dólar-dia, dólar-período, moeda-dia, moeda-período) viram
|
|
6
|
+
* UMA tool, `bcb_cambio_cotacao`, com `moeda` (padrão USD) e data única ou
|
|
7
|
+
* intervalo. Mais `bcb_cambio_moedas` para a lista de moedas, porque descobrir o
|
|
8
|
+
* símbolo é pergunta própria.
|
|
9
|
+
*
|
|
10
|
+
* Duas obrigações legais do `bcb/docs/01` nascem implementadas aqui, não no D4:
|
|
11
|
+
*
|
|
12
|
+
* 1. **O disclaimer do BCB é repassado literalmente** em toda resposta de
|
|
13
|
+
* cotação — é o único texto tipo-ToS que a fonte publica.
|
|
14
|
+
* 2. **Paridades de moedas não-dólar são QUALIFICADAS**: elas não são dado do
|
|
15
|
+
* BCB, vêm de agência de informação (Refinitiv) e são redistribuídas pelo BCB.
|
|
16
|
+
* Anunciá-las como dado do BCB sem qualificar seria incorreto.
|
|
17
|
+
*
|
|
18
|
+
* Pegadinha da API que mora em `olinda.ts`: os parâmetros de data da PTAX são
|
|
19
|
+
* **MM-DD-YYYY**, não ISO nem dd/MM/yyyy.
|
|
20
|
+
*/
|
|
21
|
+
import { type ToolDefinition, type ToolResult } from "./shared.js";
|
|
22
|
+
/** Repassado literalmente, como o `docs/01` exige. */
|
|
23
|
+
export declare const DISCLAIMER_PTAX: string;
|
|
24
|
+
export declare const QUALIFICACAO_PARIDADE: string;
|
|
25
|
+
export interface CotacaoNormalizada {
|
|
26
|
+
/** Data e hora da cotação como a fonte publica. */
|
|
27
|
+
dataHora: string | null;
|
|
28
|
+
cotacaoCompra: number | null;
|
|
29
|
+
cotacaoVenda: number | null;
|
|
30
|
+
/** Só para moedas não-dólar: paridade contra o USD (origem: agência de informação). */
|
|
31
|
+
paridadeCompra?: number | null;
|
|
32
|
+
paridadeVenda?: number | null;
|
|
33
|
+
/** Nulo em USD: verificado contra a origem, os recursos de dólar não publicam este campo. */
|
|
34
|
+
tipoBoletim: string | null;
|
|
35
|
+
}
|
|
36
|
+
export declare function normalizarCotacao(linha: Record<string, unknown>, dolar: boolean): CotacaoNormalizada;
|
|
37
|
+
interface UrlCotacao {
|
|
38
|
+
url: string;
|
|
39
|
+
dolar: boolean;
|
|
40
|
+
dataInicial: string;
|
|
41
|
+
dataFinal: string;
|
|
42
|
+
janelaPadrao: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Monta a URL da cotação escolhendo entre os quatro recursos da fonte. É o único
|
|
46
|
+
* lugar que sabe que existem quatro: para fora há uma tool só.
|
|
47
|
+
*/
|
|
48
|
+
export declare function montarUrlCotacao(args: {
|
|
49
|
+
moeda?: string;
|
|
50
|
+
data?: string;
|
|
51
|
+
dataInicial?: string;
|
|
52
|
+
dataFinal?: string;
|
|
53
|
+
}): UrlCotacao | {
|
|
54
|
+
erro: string;
|
|
55
|
+
};
|
|
56
|
+
export interface ArgsCotacao {
|
|
57
|
+
moeda?: string;
|
|
58
|
+
data?: string;
|
|
59
|
+
dataInicial?: string;
|
|
60
|
+
dataFinal?: string;
|
|
61
|
+
limite?: number;
|
|
62
|
+
}
|
|
63
|
+
export declare function handleCambioCotacao(args: ArgsCotacao, timeoutMs?: number, maxRetries?: number): Promise<ToolResult>;
|
|
64
|
+
export interface ArgsMoedas {
|
|
65
|
+
termo?: string;
|
|
66
|
+
}
|
|
67
|
+
export declare function handleCambioMoedas(args: ArgsMoedas, timeoutMs?: number, maxRetries?: number): Promise<ToolResult>;
|
|
68
|
+
export declare const CAMBIO_TOOL_DEFINITIONS: ToolDefinition[];
|
|
69
|
+
/** Retorna null quando a tool não é deste módulo (o dispatcher central segue). */
|
|
70
|
+
export declare function dispatchCambioTool(toolName: string, args: Record<string, unknown>, timeoutMs?: number, maxRetries?: number): Promise<ToolResult> | null;
|
|
71
|
+
export {};
|
|
72
|
+
//# sourceMappingURL=cambio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cambio.d.ts","sourceRoot":"","sources":["../src/cambio.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAaH,OAAO,EAA+D,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAKhI,sDAAsD;AACtD,eAAO,MAAM,eAAe,QAIO,CAAC;AAEpC,eAAO,MAAM,qBAAqB,QAGT,CAAC;AAE1B,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,uFAAuF;IACvF,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,6FAA6F;IAC7F,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAcpG;AAED,UAAU,UAAU;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CA4ChC;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,WAAW,EACjB,SAAS,CAAC,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,CA0CrB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,UAAU,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,CA8BrB;AASD,eAAO,MAAM,uBAAuB,EAAE,cAAc,EA6GnD,CAAC;AAEF,kFAAkF;AAClF,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,SAAS,CAAC,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAS5B"}
|
package/dist/cambio.js
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PTAX — cotações de câmbio e lista de moedas.
|
|
3
|
+
*
|
|
4
|
+
* Desenho aprovado (fronteira concreta da sessão de D3): os quatro recursos de
|
|
5
|
+
* cotação da fonte (dólar-dia, dólar-período, moeda-dia, moeda-período) viram
|
|
6
|
+
* UMA tool, `bcb_cambio_cotacao`, com `moeda` (padrão USD) e data única ou
|
|
7
|
+
* intervalo. Mais `bcb_cambio_moedas` para a lista de moedas, porque descobrir o
|
|
8
|
+
* símbolo é pergunta própria.
|
|
9
|
+
*
|
|
10
|
+
* Duas obrigações legais do `bcb/docs/01` nascem implementadas aqui, não no D4:
|
|
11
|
+
*
|
|
12
|
+
* 1. **O disclaimer do BCB é repassado literalmente** em toda resposta de
|
|
13
|
+
* cotação — é o único texto tipo-ToS que a fonte publica.
|
|
14
|
+
* 2. **Paridades de moedas não-dólar são QUALIFICADAS**: elas não são dado do
|
|
15
|
+
* BCB, vêm de agência de informação (Refinitiv) e são redistribuídas pelo BCB.
|
|
16
|
+
* Anunciá-las como dado do BCB sem qualificar seria incorreto.
|
|
17
|
+
*
|
|
18
|
+
* Pegadinha da API que mora em `olinda.ts`: os parâmetros de data da PTAX são
|
|
19
|
+
* **MM-DD-YYYY**, não ISO nem dd/MM/yyyy.
|
|
20
|
+
*/
|
|
21
|
+
import { PTAX_ODATA, consultarOData, hojeIso, montarUrlOData, numeroOuNulo, paraDataPtax, paraIso, somarDiasIso, textoOuNulo } from "./olinda.js";
|
|
22
|
+
import { erroResult, leituraRemota, mensagemDeErro, structuredResult } from "./shared.js";
|
|
23
|
+
/** Janela padrão quando não se informa data nenhuma: cobre feriados e fins de semana. */
|
|
24
|
+
const JANELA_PADRAO_DIAS = 7;
|
|
25
|
+
/** Repassado literalmente, como o `docs/01` exige. */
|
|
26
|
+
export const DISCLAIMER_PTAX = "O Banco Central não assume qualquer responsabilidade pela não simultaneidade ou falta das informações " +
|
|
27
|
+
"prestadas, assim como por eventuais erros de paridades das moedas. Não assume, também, responsabilidade " +
|
|
28
|
+
"por qualquer perda ou dano oriundo de tais interrupções, atrasos, falhas ou imperfeições, bem como pelo " +
|
|
29
|
+
"uso inadequado das informações.";
|
|
30
|
+
export const QUALIFICACAO_PARIDADE = "As paridades das moedas contra o dólar americano NÃO são apuradas pelo Banco Central: são obtidas junto a " +
|
|
31
|
+
"agências de informação (Refinitiv) e redistribuídas pelo BCB. Trate-as como dado de terceiro qualificado, " +
|
|
32
|
+
"não como dado do BCB.";
|
|
33
|
+
export function normalizarCotacao(linha, dolar) {
|
|
34
|
+
const normalizada = {
|
|
35
|
+
dataHora: textoOuNulo(linha.dataHoraCotacao),
|
|
36
|
+
cotacaoCompra: numeroOuNulo(linha.cotacaoCompra),
|
|
37
|
+
cotacaoVenda: numeroOuNulo(linha.cotacaoVenda),
|
|
38
|
+
tipoBoletim: textoOuNulo(linha.tipoBoletim)
|
|
39
|
+
};
|
|
40
|
+
if (!dolar) {
|
|
41
|
+
normalizada.paridadeCompra = numeroOuNulo(linha.paridadeCompra);
|
|
42
|
+
normalizada.paridadeVenda = numeroOuNulo(linha.paridadeVenda);
|
|
43
|
+
}
|
|
44
|
+
return normalizada;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Monta a URL da cotação escolhendo entre os quatro recursos da fonte. É o único
|
|
48
|
+
* lugar que sabe que existem quatro: para fora há uma tool só.
|
|
49
|
+
*/
|
|
50
|
+
export function montarUrlCotacao(args) {
|
|
51
|
+
const moeda = (args.moeda ?? "USD").toUpperCase();
|
|
52
|
+
const dolar = moeda === "USD";
|
|
53
|
+
let inicio;
|
|
54
|
+
let fim;
|
|
55
|
+
let janelaPadrao = false;
|
|
56
|
+
if (args.data !== undefined) {
|
|
57
|
+
if (args.dataInicial !== undefined || args.dataFinal !== undefined) {
|
|
58
|
+
return { erro: "Use `data` para um dia específico OU `dataInicial`/`dataFinal` para um intervalo, não os dois." };
|
|
59
|
+
}
|
|
60
|
+
inicio = paraIso(args.data);
|
|
61
|
+
if (!inicio)
|
|
62
|
+
return { erro: `data inválida: "${args.data}". Use yyyy-MM-dd ou dd/MM/yyyy.` };
|
|
63
|
+
fim = inicio;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
fim = args.dataFinal ? paraIso(args.dataFinal) : hojeIso();
|
|
67
|
+
if (!fim)
|
|
68
|
+
return { erro: `dataFinal inválida: "${args.dataFinal}". Use yyyy-MM-dd ou dd/MM/yyyy.` };
|
|
69
|
+
inicio = args.dataInicial ? paraIso(args.dataInicial) : somarDiasIso(fim, -JANELA_PADRAO_DIAS);
|
|
70
|
+
if (!inicio)
|
|
71
|
+
return { erro: `dataInicial inválida: "${args.dataInicial}". Use yyyy-MM-dd ou dd/MM/yyyy.` };
|
|
72
|
+
janelaPadrao = args.dataInicial === undefined && args.dataFinal === undefined;
|
|
73
|
+
}
|
|
74
|
+
if (inicio > fim) {
|
|
75
|
+
return { erro: `A janela está invertida: dataInicial (${inicio}) é posterior a dataFinal (${fim}).` };
|
|
76
|
+
}
|
|
77
|
+
const diaUnico = inicio === fim && args.data !== undefined;
|
|
78
|
+
const pInicio = paraDataPtax(inicio);
|
|
79
|
+
const pFim = paraDataPtax(fim);
|
|
80
|
+
// Recursos parametrizados do OData: os argumentos vão como @parâmetros.
|
|
81
|
+
const recurso = diaUnico
|
|
82
|
+
? dolar
|
|
83
|
+
? `CotacaoDolarDia(dataCotacao=@dataCotacao)?@dataCotacao='${pInicio}'`
|
|
84
|
+
: `CotacaoMoedaDia(moeda=@moeda,dataCotacao=@dataCotacao)?@moeda='${moeda}'&@dataCotacao='${pInicio}'`
|
|
85
|
+
: dolar
|
|
86
|
+
? `CotacaoDolarPeriodo(dataInicial=@dataInicial,dataFinalCotacao=@dataFinalCotacao)?@dataInicial='${pInicio}'&@dataFinalCotacao='${pFim}'`
|
|
87
|
+
: `CotacaoMoedaPeriodo(moeda=@moeda,dataInicial=@dataInicial,dataFinalCotacao=@dataFinalCotacao)?@moeda='${moeda}'&@dataInicial='${pInicio}'&@dataFinalCotacao='${pFim}'`;
|
|
88
|
+
// O recurso já carrega query string, então o formato entra com `&`.
|
|
89
|
+
const url = `${PTAX_ODATA}/${recurso}&$format=json`;
|
|
90
|
+
return { url, dolar, dataInicial: inicio, dataFinal: fim, janelaPadrao };
|
|
91
|
+
}
|
|
92
|
+
export async function handleCambioCotacao(args, timeoutMs, maxRetries) {
|
|
93
|
+
const montada = montarUrlCotacao(args);
|
|
94
|
+
if ("erro" in montada)
|
|
95
|
+
return erroResult(montada.erro);
|
|
96
|
+
try {
|
|
97
|
+
const linhas = await consultarOData(montada.url, timeoutMs, maxRetries);
|
|
98
|
+
const limite = args.limite ?? 100;
|
|
99
|
+
const todas = linhas
|
|
100
|
+
.map(l => normalizarCotacao(l, montada.dolar))
|
|
101
|
+
.sort((a, b) => (b.dataHora ?? "").localeCompare(a.dataHora ?? ""));
|
|
102
|
+
const cotacoes = todas.slice(0, limite);
|
|
103
|
+
const payload = {
|
|
104
|
+
moeda: (args.moeda ?? "USD").toUpperCase(),
|
|
105
|
+
periodo: {
|
|
106
|
+
dataInicial: montada.dataInicial,
|
|
107
|
+
dataFinal: montada.dataFinal,
|
|
108
|
+
janelaPadrao: montada.janelaPadrao
|
|
109
|
+
},
|
|
110
|
+
totalRegistros: todas.length,
|
|
111
|
+
cotacoes,
|
|
112
|
+
disclaimer: DISCLAIMER_PTAX,
|
|
113
|
+
urlConsulta: montada.url,
|
|
114
|
+
consultadoEm: new Date().toISOString()
|
|
115
|
+
};
|
|
116
|
+
if (!montada.dolar)
|
|
117
|
+
payload.qualificacaoParidade = QUALIFICACAO_PARIDADE;
|
|
118
|
+
if (cotacoes.length < todas.length) {
|
|
119
|
+
payload.observacao = `Exibindo ${cotacoes.length} de ${todas.length} boletins; aumente 'limite' ou estreite o período.`;
|
|
120
|
+
}
|
|
121
|
+
if (todas.length === 0) {
|
|
122
|
+
payload.observacao =
|
|
123
|
+
"Nenhuma cotação no período. A PTAX só existe em dia útil com fechamento de câmbio — fim de semana, " +
|
|
124
|
+
"feriado e o próprio dia antes do fechamento voltam vazios. Confirme também o símbolo da moeda com " +
|
|
125
|
+
"bcb_cambio_moedas.";
|
|
126
|
+
}
|
|
127
|
+
return structuredResult(payload);
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
return erroResult(`Erro ao consultar cotação de câmbio: ${mensagemDeErro(error)}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
export async function handleCambioMoedas(args, timeoutMs, maxRetries) {
|
|
134
|
+
const url = montarUrlOData(PTAX_ODATA, { recurso: "Moedas" });
|
|
135
|
+
try {
|
|
136
|
+
const linhas = await consultarOData(url, timeoutMs, maxRetries);
|
|
137
|
+
let moedas = linhas.map(l => ({
|
|
138
|
+
simbolo: textoOuNulo(l.simbolo),
|
|
139
|
+
nome: textoOuNulo(l.nomeFormatado),
|
|
140
|
+
tipo: textoOuNulo(l.tipoMoeda)
|
|
141
|
+
}));
|
|
142
|
+
if (args.termo !== undefined) {
|
|
143
|
+
const termo = args.termo.toUpperCase();
|
|
144
|
+
moedas = moedas.filter(m => (m.simbolo ?? "").includes(termo) || (m.nome ?? "").toUpperCase().includes(termo));
|
|
145
|
+
}
|
|
146
|
+
return structuredResult({
|
|
147
|
+
termo: args.termo ?? null,
|
|
148
|
+
totalMoedas: moedas.length,
|
|
149
|
+
moedas,
|
|
150
|
+
disclaimer: DISCLAIMER_PTAX,
|
|
151
|
+
qualificacaoParidade: QUALIFICACAO_PARIDADE,
|
|
152
|
+
urlConsulta: url,
|
|
153
|
+
consultadoEm: new Date().toISOString(),
|
|
154
|
+
observacao: "Use o `simbolo` em bcb_cambio_cotacao. O dólar americano (USD) é o padrão da tool de cotação."
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
return erroResult(`Erro ao listar moedas: ${mensagemDeErro(error)}`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// ==================== SCHEMAS ====================
|
|
162
|
+
const NOTA_PTAX = "Fonte: PTAX / Cotações e boletins de câmbio do Banco Central do Brasil, via Olinda OData. A resposta repassa " +
|
|
163
|
+
"literalmente o disclaimer de responsabilidade do BCB, em `disclaimer`. Cotações existem só em dia útil com " +
|
|
164
|
+
"fechamento de câmbio.";
|
|
165
|
+
export const CAMBIO_TOOL_DEFINITIONS = [
|
|
166
|
+
{
|
|
167
|
+
name: "bcb_cambio_cotacao",
|
|
168
|
+
description: "Consulta a cotação PTAX de uma moeda contra o real, em um dia específico ou num intervalo de datas. " +
|
|
169
|
+
"Padrão: dólar americano (USD). Devolve compra, venda, data/hora e tipo de boletim; para moedas " +
|
|
170
|
+
"não-dólar devolve também a paridade contra o USD, com a origem qualificada. " +
|
|
171
|
+
"Quando usar: para a cotação oficial de fechamento de um dia ou a série de um período curto. " +
|
|
172
|
+
"Quando NÃO usar: para a série histórica longa do dólar como série temporal do SGS use bcb_serie_valores " +
|
|
173
|
+
"(códigos 1 = livre venda, 3698 = PTAX venda, 3697 = PTAX compra, 3695 = PTAX média) — esta tool é a " +
|
|
174
|
+
"fonte primária do boletim, com compra e venda no mesmo registro; para descobrir o símbolo da moeda use " +
|
|
175
|
+
"bcb_cambio_moedas. " +
|
|
176
|
+
"Retorna: `moeda`, `periodo` (dataInicial, dataFinal, janelaPadrao), `totalRegistros`, `cotacoes`, " +
|
|
177
|
+
"`disclaimer`, `qualificacaoParidade` (só para moedas não-dólar), `urlConsulta`, `consultadoEm` e, quando " +
|
|
178
|
+
"aplicável, `observacao`. Sem datas, cobre os últimos 7 dias (para atravessar fim de semana e feriado). " +
|
|
179
|
+
NOTA_PTAX +
|
|
180
|
+
" As paridades de moedas não-dólar vêm de agência de informação (Refinitiv), redistribuídas pelo BCB — não " +
|
|
181
|
+
"são apuradas pelo Banco Central.",
|
|
182
|
+
annotations: leituraRemota("Cotação de câmbio (PTAX)"),
|
|
183
|
+
inputSchema: {
|
|
184
|
+
type: "object",
|
|
185
|
+
properties: {
|
|
186
|
+
moeda: { type: "string", description: "Símbolo da moeda (ex.: USD, EUR, GBP, JPY). Padrão: USD.", default: "USD" },
|
|
187
|
+
data: { type: "string", description: "Dia específico (yyyy-MM-dd ou dd/MM/yyyy). Não combine com dataInicial/dataFinal." },
|
|
188
|
+
dataInicial: { type: "string", description: "Início do intervalo (yyyy-MM-dd ou dd/MM/yyyy). Padrão: 7 dias antes do fim." },
|
|
189
|
+
dataFinal: { type: "string", description: "Fim do intervalo (yyyy-MM-dd ou dd/MM/yyyy). Padrão: hoje." },
|
|
190
|
+
limite: { type: "number", description: "Máximo de boletins a devolver (1-1000, padrão 100)", default: 100, minimum: 1, maximum: 1000 }
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
outputSchema: {
|
|
194
|
+
type: "object",
|
|
195
|
+
properties: {
|
|
196
|
+
moeda: { type: "string" },
|
|
197
|
+
periodo: {
|
|
198
|
+
type: "object",
|
|
199
|
+
properties: {
|
|
200
|
+
dataInicial: { type: "string" },
|
|
201
|
+
dataFinal: { type: "string" },
|
|
202
|
+
janelaPadrao: { type: "boolean", description: "true quando a janela de 7 dias foi assumida" }
|
|
203
|
+
},
|
|
204
|
+
required: ["dataInicial", "dataFinal", "janelaPadrao"]
|
|
205
|
+
},
|
|
206
|
+
totalRegistros: { type: "number" },
|
|
207
|
+
cotacoes: {
|
|
208
|
+
type: "array",
|
|
209
|
+
items: {
|
|
210
|
+
type: "object",
|
|
211
|
+
properties: {
|
|
212
|
+
dataHora: { type: ["string", "null"], description: "Data e hora da cotação" },
|
|
213
|
+
cotacaoCompra: { type: ["number", "null"] },
|
|
214
|
+
cotacaoVenda: { type: ["number", "null"] },
|
|
215
|
+
paridadeCompra: { type: ["number", "null"], description: "Paridade de compra contra o USD (moedas não-dólar; origem: agência de informação)" },
|
|
216
|
+
paridadeVenda: { type: ["number", "null"], description: "Paridade de venda contra o USD (moedas não-dólar; origem: agência de informação)" },
|
|
217
|
+
tipoBoletim: { type: ["string", "null"], description: "Tipo de boletim (ex.: Fechamento, Abertura, Intermediário). Nulo em USD: a fonte não publica este campo nos recursos de dólar, só nos de moeda." }
|
|
218
|
+
},
|
|
219
|
+
required: ["dataHora"]
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
disclaimer: { type: "string", description: "Disclaimer de responsabilidade do BCB, repassado literalmente" },
|
|
223
|
+
qualificacaoParidade: { type: "string", description: "Qualificação da origem das paridades não-dólar" },
|
|
224
|
+
urlConsulta: { type: "string" },
|
|
225
|
+
consultadoEm: { type: "string" },
|
|
226
|
+
observacao: { type: "string" }
|
|
227
|
+
},
|
|
228
|
+
required: ["moeda", "periodo", "totalRegistros", "cotacoes", "disclaimer", "urlConsulta", "consultadoEm"]
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: "bcb_cambio_moedas",
|
|
233
|
+
description: "Lista as moedas com cotação publicada pelo Banco Central, com símbolo, nome e tipo, e aceita um termo " +
|
|
234
|
+
"para filtrar. " +
|
|
235
|
+
"Quando usar: para descobrir o símbolo correto antes de chamar bcb_cambio_cotacao (é a causa mais comum " +
|
|
236
|
+
"de cotação vazia). Quando NÃO usar: para valores de cotação. " +
|
|
237
|
+
"Retorna: `termo`, `totalMoedas`, `moedas` (simbolo, nome, tipo), `disclaimer`, `qualificacaoParidade`, " +
|
|
238
|
+
"`urlConsulta` e `consultadoEm`. " + NOTA_PTAX,
|
|
239
|
+
annotations: leituraRemota("Moedas com cotação no BCB"),
|
|
240
|
+
inputSchema: {
|
|
241
|
+
type: "object",
|
|
242
|
+
properties: {
|
|
243
|
+
termo: { type: "string", description: "Filtro por símbolo ou nome (ex.: 'EUR', 'libra'). Opcional." }
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
outputSchema: {
|
|
247
|
+
type: "object",
|
|
248
|
+
properties: {
|
|
249
|
+
termo: { type: ["string", "null"], description: "Termo aplicado no filtro; nulo quando não foi informado" },
|
|
250
|
+
totalMoedas: { type: "number" },
|
|
251
|
+
moedas: {
|
|
252
|
+
type: "array",
|
|
253
|
+
items: {
|
|
254
|
+
type: "object",
|
|
255
|
+
properties: {
|
|
256
|
+
simbolo: { type: ["string", "null"], description: "Símbolo a usar em bcb_cambio_cotacao" },
|
|
257
|
+
nome: { type: ["string", "null"] },
|
|
258
|
+
tipo: { type: ["string", "null"], description: "Tipo da moeda conforme a fonte (A ou B)" }
|
|
259
|
+
},
|
|
260
|
+
required: ["simbolo"]
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
disclaimer: { type: "string" },
|
|
264
|
+
qualificacaoParidade: { type: "string" },
|
|
265
|
+
urlConsulta: { type: "string" },
|
|
266
|
+
consultadoEm: { type: "string" },
|
|
267
|
+
observacao: { type: "string" }
|
|
268
|
+
},
|
|
269
|
+
required: ["totalMoedas", "moedas", "disclaimer", "urlConsulta", "consultadoEm"]
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
];
|
|
273
|
+
/** Retorna null quando a tool não é deste módulo (o dispatcher central segue). */
|
|
274
|
+
export function dispatchCambioTool(toolName, args, timeoutMs, maxRetries) {
|
|
275
|
+
switch (toolName) {
|
|
276
|
+
case "bcb_cambio_cotacao":
|
|
277
|
+
return handleCambioCotacao(args, timeoutMs, maxRetries);
|
|
278
|
+
case "bcb_cambio_moedas":
|
|
279
|
+
return handleCambioMoedas(args, timeoutMs, maxRetries);
|
|
280
|
+
default:
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
//# sourceMappingURL=cambio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cambio.js","sourceRoot":"","sources":["../src/cambio.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EACL,UAAU,EACV,cAAc,EACd,OAAO,EACP,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,WAAW,EACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAwC,MAAM,aAAa,CAAC;AAEhI,yFAAyF;AACzF,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAE7B,sDAAsD;AACtD,MAAM,CAAC,MAAM,eAAe,GAC1B,wGAAwG;IACxG,0GAA0G;IAC1G,0GAA0G;IAC1G,iCAAiC,CAAC;AAEpC,MAAM,CAAC,MAAM,qBAAqB,GAChC,4GAA4G;IAC5G,4GAA4G;IAC5G,uBAAuB,CAAC;AAc1B,MAAM,UAAU,iBAAiB,CAAC,KAA8B,EAAE,KAAc;IAC9E,MAAM,WAAW,GAAuB;QACtC,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC,eAAe,CAAC;QAC5C,aAAa,EAAE,YAAY,CAAC,KAAK,CAAC,aAAa,CAAC;QAChD,YAAY,EAAE,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC;QAC9C,WAAW,EAAE,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC;KAC5C,CAAC;IAEF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,WAAW,CAAC,cAAc,GAAG,YAAY,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAChE,WAAW,CAAC,aAAa,GAAG,YAAY,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC;AAUD;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAKhC;IACC,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;IAClD,MAAM,KAAK,GAAG,KAAK,KAAK,KAAK,CAAC;IAE9B,IAAI,MAAqB,CAAC;IAC1B,IAAI,GAAkB,CAAC;IACvB,IAAI,YAAY,GAAG,KAAK,CAAC;IAEzB,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACnE,OAAO,EAAE,IAAI,EAAE,gGAAgG,EAAE,CAAC;QACpH,CAAC;QACD,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,IAAI,EAAE,mBAAmB,IAAI,CAAC,IAAI,kCAAkC,EAAE,CAAC;QAC7F,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;SAAM,CAAC;QACN,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QAC3D,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,IAAI,EAAE,wBAAwB,IAAI,CAAC,SAAS,kCAAkC,EAAE,CAAC;QACpG,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,CAAC;QAC/F,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,IAAI,EAAE,0BAA0B,IAAI,CAAC,WAAW,kCAAkC,EAAE,CAAC;QAC3G,YAAY,GAAG,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC;IAChF,CAAC;IAED,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,yCAAyC,MAAM,8BAA8B,GAAG,IAAI,EAAE,CAAC;IACxG,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC;IAC3D,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAE/B,wEAAwE;IACxE,MAAM,OAAO,GAAG,QAAQ;QACtB,CAAC,CAAC,KAAK;YACL,CAAC,CAAC,2DAA2D,OAAO,GAAG;YACvE,CAAC,CAAC,kEAAkE,KAAK,mBAAmB,OAAO,GAAG;QACxG,CAAC,CAAC,KAAK;YACL,CAAC,CAAC,kGAAkG,OAAO,wBAAwB,IAAI,GAAG;YAC1I,CAAC,CAAC,yGAAyG,KAAK,mBAAmB,OAAO,wBAAwB,IAAI,GAAG,CAAC;IAE9K,oEAAoE;IACpE,MAAM,GAAG,GAAG,GAAG,UAAU,IAAI,OAAO,eAAe,CAAC;IAEpD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC;AAC3E,CAAC;AAUD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAiB,EACjB,SAAkB,EAClB,UAAmB;IAEnB,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,MAAM,IAAI,OAAO;QAAE,OAAO,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACxE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC;QAClC,MAAM,KAAK,GAAG,MAAM;aACjB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;aAC7C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC;QACtE,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAExC,MAAM,OAAO,GAA4B;YACvC,KAAK,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE;YAC1C,OAAO,EAAE;gBACP,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,YAAY,EAAE,OAAO,CAAC,YAAY;aACnC;YACD,cAAc,EAAE,KAAK,CAAC,MAAM;YAC5B,QAAQ;YACR,UAAU,EAAE,eAAe;YAC3B,WAAW,EAAE,OAAO,CAAC,GAAG;YACxB,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACvC,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,KAAK;YAAE,OAAO,CAAC,oBAAoB,GAAG,qBAAqB,CAAC;QAEzE,IAAI,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YACnC,OAAO,CAAC,UAAU,GAAG,YAAY,QAAQ,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,oDAAoD,CAAC;QAC1H,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,UAAU;gBAChB,qGAAqG;oBACrG,oGAAoG;oBACpG,oBAAoB,CAAC;QACzB,CAAC;QAED,OAAO,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,UAAU,CAAC,wCAAwC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrF,CAAC;AACH,CAAC;AAMD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAgB,EAChB,SAAkB,EAClB,UAAmB;IAEnB,MAAM,GAAG,GAAG,cAAc,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;IAE9D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QAEhE,IAAI,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5B,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/B,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC;YAClC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;SAC/B,CAAC,CAAC,CAAC;QAEJ,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YACvC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QACjH,CAAC;QAED,OAAO,gBAAgB,CAAC;YACtB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI;YACzB,WAAW,EAAE,MAAM,CAAC,MAAM;YAC1B,MAAM;YACN,UAAU,EAAE,eAAe;YAC3B,oBAAoB,EAAE,qBAAqB;YAC3C,WAAW,EAAE,GAAG;YAChB,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACtC,UAAU,EAAE,+FAA+F;SAC5G,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,UAAU,CAAC,0BAA0B,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAED,oDAAoD;AAEpD,MAAM,SAAS,GACb,+GAA+G;IAC/G,6GAA6G;IAC7G,uBAAuB,CAAC;AAE1B,MAAM,CAAC,MAAM,uBAAuB,GAAqB;IACvD;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EACT,sGAAsG;YACtG,iGAAiG;YACjG,8EAA8E;YAC9E,8FAA8F;YAC9F,0GAA0G;YAC1G,sGAAsG;YACtG,yGAAyG;YACzG,qBAAqB;YACrB,oGAAoG;YACpG,2GAA2G;YAC3G,yGAAyG;YACzG,SAAS;YACT,4GAA4G;YAC5G,kCAAkC;QACpC,WAAW,EAAE,aAAa,CAAC,0BAA0B,CAAC;QACtD,WAAW,EAAE;YACX,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE;gBACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,0DAA0D,EAAE,OAAO,EAAE,KAAK,EAAE;gBAC3H,IAAI,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,mFAAmF,EAAE;gBACnI,WAAW,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,8EAA8E,EAAE;gBACrI,SAAS,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,4DAA4D,EAAE;gBACjH,MAAM,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,oDAAoD,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;aAChJ;SACF;QACD,YAAY,EAAE;YACZ,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE;gBACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE;gBAClC,OAAO,EAAE;oBACP,IAAI,EAAE,QAAiB;oBACvB,UAAU,EAAE;wBACV,WAAW,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE;wBACxC,SAAS,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE;wBACtC,YAAY,EAAE,EAAE,IAAI,EAAE,SAAkB,EAAE,WAAW,EAAE,6CAA6C,EAAE;qBACvG;oBACD,QAAQ,EAAE,CAAC,aAAa,EAAE,WAAW,EAAE,cAAc,CAAC;iBACvD;gBACD,cAAc,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE;gBAC3C,QAAQ,EAAE;oBACR,IAAI,EAAE,OAAgB;oBACtB,KAAK,EAAE;wBACL,IAAI,EAAE,QAAiB;wBACvB,UAAU,EAAE;4BACV,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAU,EAAE,WAAW,EAAE,wBAAwB,EAAE;4BACtF,aAAa,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAU,EAAE;4BACpD,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAU,EAAE;4BACnD,cAAc,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAU,EAAE,WAAW,EAAE,mFAAmF,EAAE;4BACvJ,aAAa,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAU,EAAE,WAAW,EAAE,kFAAkF,EAAE;4BACrJ,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAU,EAAE,WAAW,EAAE,iJAAiJ,EAAE;yBACnN;wBACD,QAAQ,EAAE,CAAC,UAAU,CAAC;qBACvB;iBACF;gBACD,UAAU,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,+DAA+D,EAAE;gBACrH,oBAAoB,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,gDAAgD,EAAE;gBAChH,WAAW,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE;gBACxC,YAAY,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE;gBACzC,UAAU,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE;aACxC;YACD,QAAQ,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,CAAC;SAC1G;KACF;IACD;QACE,IAAI,EAAE,mBAAmB;QACzB,WAAW,EACT,wGAAwG;YACxG,gBAAgB;YAChB,yGAAyG;YACzG,+DAA+D;YAC/D,yGAAyG;YACzG,kCAAkC,GAAG,SAAS;QAChD,WAAW,EAAE,aAAa,CAAC,2BAA2B,CAAC;QACvD,WAAW,EAAE;YACX,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE;gBACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,6DAA6D,EAAE;aAC/G;SACF;QACD,YAAY,EAAE;YACZ,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE;gBACV,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAU,EAAE,WAAW,EAAE,yDAAyD,EAAE;gBACpH,WAAW,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE;gBACxC,MAAM,EAAE;oBACN,IAAI,EAAE,OAAgB;oBACtB,KAAK,EAAE;wBACL,IAAI,EAAE,QAAiB;wBACvB,UAAU,EAAE;4BACV,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAU,EAAE,WAAW,EAAE,sCAAsC,EAAE;4BACnG,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAU,EAAE;4BAC3C,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAU,EAAE,WAAW,EAAE,yCAAyC,EAAE;yBACpG;wBACD,QAAQ,EAAE,CAAC,SAAS,CAAC;qBACtB;iBACF;gBACD,UAAU,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE;gBACvC,oBAAoB,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE;gBACjD,WAAW,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE;gBACxC,YAAY,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE;gBACzC,UAAU,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE;aACxC;YACD,QAAQ,EAAE,CAAC,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,CAAC;SACjF;KACF;CACF,CAAC;AAEF,kFAAkF;AAClF,MAAM,UAAU,kBAAkB,CAChC,QAAgB,EAChB,IAA6B,EAC7B,SAAkB,EAClB,UAAmB;IAEnB,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,oBAAoB;YACvB,OAAO,mBAAmB,CAAC,IAA8B,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACpF,KAAK,mBAAmB;YACtB,OAAO,kBAAkB,CAAC,IAA6B,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QAClF;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Índice de séries do Portal de Dados Abertos do BCB (CKAN) — busca real.
|
|
3
|
+
*
|
|
4
|
+
* Desenho fechado pelo decisor na fase bcb (arbitragem 5), e as restrições
|
|
5
|
+
* importam mais que o código:
|
|
6
|
+
*
|
|
7
|
+
* - Fonte é `package_list` do CKAN: UMA requisição (~310 KB) devolve o nome de
|
|
8
|
+
* todos os datasets do portal, e 3.555 deles são nomeados pelo próprio código
|
|
9
|
+
* da série (`{codigo}-{slug}`) — ~24× a cobertura do catálogo curado local.
|
|
10
|
+
* Nada de raspar o localizador JSP do SGS.
|
|
11
|
+
* - O catálogo é servido de cache com validade de 24 h e a renovação é
|
|
12
|
+
* BLOQUEANTE: quem faz a primeira busca depois do vencimento paga o ~0,8 s.
|
|
13
|
+
* Sem tarefa agendada e sem seed manual — se ninguém buscar, a origem não
|
|
14
|
+
* recebe requisição nenhuma. Descartado de propósito o
|
|
15
|
+
* stale-while-revalidate: com tráfego baixo ele entregaria retrato de semanas
|
|
16
|
+
* ao primeiro usuário para poupar 0,8 s de um único usuário por dia.
|
|
17
|
+
* - O cache guarda **só metadados** (código e slug), NUNCA observações. É por
|
|
18
|
+
* isso que ele não é a "base derivada" que a arbitragem 2 evitou: o servidor
|
|
19
|
+
* segue sendo *Produced Work* sob a ODbL, e valores de série continuam
|
|
20
|
+
* buscados ao vivo a cada pergunta.
|
|
21
|
+
* - `Disallow: /api/` + `Crawl-Delay: 10` no robots do portal do catálogo é o
|
|
22
|
+
* motivo de existir cache: ≤1 requisição por dia por instância, não uma por
|
|
23
|
+
* chamada.
|
|
24
|
+
*
|
|
25
|
+
* O cache é módulo-level, ou seja, por processo (stdio) e por isolate
|
|
26
|
+
* (Cloudflare). Isolate reciclado = catálogo buscado de novo; com o tráfego
|
|
27
|
+
* atual isso mantém a ordem de grandeza prometida (unidades de requisição por
|
|
28
|
+
* dia), e é a única forma de cache que não introduz armazenamento persistente.
|
|
29
|
+
*/
|
|
30
|
+
import { type SeriePopular } from "./shared.js";
|
|
31
|
+
export declare const CKAN_PACKAGE_LIST = "https://dadosabertos.bcb.gov.br/api/3/action/package_list";
|
|
32
|
+
export declare const CKAN_DATASET_BASE = "https://dadosabertos.bcb.gov.br/dataset";
|
|
33
|
+
/** Validade do catálogo em cache: 24 h (decisão do decisor). */
|
|
34
|
+
export declare const CATALOGO_TTL_MS: number;
|
|
35
|
+
/** Uma entrada do índice: código da série + slug do dataset. Só metadados. */
|
|
36
|
+
export interface EntradaCatalogo {
|
|
37
|
+
codigo: number;
|
|
38
|
+
slug: string;
|
|
39
|
+
}
|
|
40
|
+
export interface SnapshotCatalogo {
|
|
41
|
+
entradas: EntradaCatalogo[];
|
|
42
|
+
/** ISO 8601 do momento em que o índice foi obtido da origem. */
|
|
43
|
+
obtidoEm: string;
|
|
44
|
+
/** Total de datasets devolvidos pelo portal (inclui os sem código). */
|
|
45
|
+
totalDatasets: number;
|
|
46
|
+
expiraEm: number;
|
|
47
|
+
}
|
|
48
|
+
export interface ResultadoCatalogo {
|
|
49
|
+
snapshot: SnapshotCatalogo | null;
|
|
50
|
+
/** Preenchido quando o índice servido não é o ideal (vencido, ou ausente). */
|
|
51
|
+
aviso?: string;
|
|
52
|
+
}
|
|
53
|
+
/** Só para os testes: zera o cache do módulo. */
|
|
54
|
+
export declare function _resetCatalogo(): void;
|
|
55
|
+
/** Só para os testes: injeta um snapshot como se tivesse vindo da origem. */
|
|
56
|
+
export declare function _seedCatalogo(snapshot: SnapshotCatalogo): void;
|
|
57
|
+
/**
|
|
58
|
+
* Conserta mojibake de ISO-8859-1 servido como UTF-8 ("Câmbio" -> "Câmbio").
|
|
59
|
+
* Os slugs do `package_list` são ASCII, então isto é defesa para os campos de
|
|
60
|
+
* texto do CKAN que já apareceram corrompidos na verificação de abertura.
|
|
61
|
+
*/
|
|
62
|
+
export declare function normalizarMojibake(texto: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Nome legível a partir do slug do dataset. O `package_list` devolve slug, não
|
|
65
|
+
* título: `---` é separador de campos e `-` separa palavras, e os acentos foram
|
|
66
|
+
* perdidos na origem — daí o nome reconstruído ser aproximado de propósito. Para
|
|
67
|
+
* as séries do catálogo curado o nome bom (com acento) prevalece; para as
|
|
68
|
+
* demais, quem quiser o nome oficial usa `bcb_serie_metadados`.
|
|
69
|
+
*/
|
|
70
|
+
export declare function nomeDoSlug(slug: string): string;
|
|
71
|
+
/** `1-taxa-de-cambio---livre---dolar-americano-venda---diario` -> {1, slug}. */
|
|
72
|
+
export declare function parsePackageList(nomes: unknown): {
|
|
73
|
+
entradas: EntradaCatalogo[];
|
|
74
|
+
totalDatasets: number;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Devolve o índice do portal, renovando de forma bloqueante quando vencido.
|
|
78
|
+
*
|
|
79
|
+
* Degradação: se a renovação falhar e houver retrato anterior, ele é servido
|
|
80
|
+
* COM aviso e com a data de obtenção visível — a API do BCB cai de verdade
|
|
81
|
+
* (ocorreu durante esta fase), e nesse caso é melhor um índice velho declarado
|
|
82
|
+
* do que busca nenhuma. Sem retrato anterior, devolve `snapshot: null` e quem
|
|
83
|
+
* chamou cai no catálogo curado.
|
|
84
|
+
*/
|
|
85
|
+
export declare function obterCatalogo(timeoutMs?: number, maxRetries?: number): Promise<ResultadoCatalogo>;
|
|
86
|
+
export type OrigemSerie = "curado" | "indice";
|
|
87
|
+
export interface SerieEncontrada {
|
|
88
|
+
codigo: number;
|
|
89
|
+
nome: string;
|
|
90
|
+
categoria?: string;
|
|
91
|
+
periodicidade?: string;
|
|
92
|
+
/** `curado` = catálogo local com nome/categoria revisados; `indice` = portal. */
|
|
93
|
+
origem: OrigemSerie;
|
|
94
|
+
/** Página do dataset no portal (só para achados do índice). */
|
|
95
|
+
dataset?: string;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Ranqueia os achados. O catálogo curado é a CAMADA DE DESTAQUE: quando uma
|
|
99
|
+
* série está nele, ela vem primeiro e com o nome bom, porque foi revisada à
|
|
100
|
+
* mão; o índice do portal entra depois, ordenado do slug mais curto (mais
|
|
101
|
+
* específico) para o mais longo, com desempate estável pelo código.
|
|
102
|
+
*/
|
|
103
|
+
export declare function buscarSeries(termo: string, curadoria: SeriePopular[], entradas: EntradaCatalogo[] | null, limite: number): {
|
|
104
|
+
total: number;
|
|
105
|
+
series: SerieEncontrada[];
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAKH,OAAO,EAAgC,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAE9E,eAAO,MAAM,iBAAiB,8DAA8D,CAAC;AAC7F,eAAO,MAAM,iBAAiB,4CAA4C,CAAC;AAE3E,gEAAgE;AAChE,eAAO,MAAM,eAAe,QAAsB,CAAC;AAEnD,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD,iDAAiD;AACjD,wBAAgB,cAAc,IAAI,IAAI,CAGrC;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAE9D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQxD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ/C;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG;IAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAkBvG;AAwBD;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA+BvG;AAID,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE9C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,MAAM,EAAE,WAAW,CAAC;IACpB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAqBD;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,YAAY,EAAE,EACzB,QAAQ,EAAE,eAAe,EAAE,GAAG,IAAI,EAClC,MAAM,EAAE,MAAM,GACb;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,CA6B9C"}
|