yuzuha 0.1.7 → 0.2.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/CHANGELOG.md +44 -0
- package/README.md +21 -4
- package/VERSIONING.md +78 -6
- package/assets/canvas/Inter-Bold.ttf +0 -0
- package/assets/canvas/Inter-Regular.ttf +0 -0
- package/assets/canvas/OFL.txt +92 -0
- package/assets/canvas/ORIGIN.md +8 -0
- package/benchmarks/rate-limits.mjs +138 -0
- package/benchmarks/results/rate-limits-comparison.json +273 -0
- package/bridges/lavalink/README.md +2 -2
- package/dist/canvas.d.ts +10 -0
- package/dist/canvas.d.ts.map +1 -0
- package/dist/canvas.js +11 -0
- package/dist/canvas.js.map +1 -0
- package/dist/cli/arguments.d.ts +5 -0
- package/dist/cli/arguments.d.ts.map +1 -1
- package/dist/cli/arguments.js +31 -6
- package/dist/cli/arguments.js.map +1 -1
- package/dist/cli/bot-template-catalog.d.ts +33 -0
- package/dist/cli/bot-template-catalog.d.ts.map +1 -0
- package/dist/cli/bot-template-catalog.js +20 -0
- package/dist/cli/bot-template-catalog.js.map +1 -0
- package/dist/cli/bot-template-commands.d.ts +2 -0
- package/dist/cli/bot-template-commands.d.ts.map +1 -0
- package/dist/cli/bot-template-commands.js +358 -0
- package/dist/cli/bot-template-commands.js.map +1 -0
- package/dist/cli/bot-template-content.d.ts +13 -0
- package/dist/cli/bot-template-content.d.ts.map +1 -0
- package/dist/cli/bot-template-content.js +69 -0
- package/dist/cli/bot-template-content.js.map +1 -0
- package/dist/cli/bot-template-feature-tests.d.ts +2 -0
- package/dist/cli/bot-template-feature-tests.d.ts.map +1 -0
- package/dist/cli/bot-template-feature-tests.js +165 -0
- package/dist/cli/bot-template-feature-tests.js.map +1 -0
- package/dist/cli/bot-template-tests.d.ts +3 -0
- package/dist/cli/bot-template-tests.d.ts.map +1 -0
- package/dist/cli/bot-template-tests.js +67 -0
- package/dist/cli/bot-template-tests.js.map +1 -0
- package/dist/cli/bot-templates.d.ts +3 -0
- package/dist/cli/bot-templates.d.ts.map +1 -0
- package/dist/cli/bot-templates.js +154 -0
- package/dist/cli/bot-templates.js.map +1 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +7 -1
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/scaffold.d.ts +3 -1
- package/dist/cli/scaffold.d.ts.map +1 -1
- package/dist/cli/scaffold.js +26 -8
- package/dist/cli/scaffold.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/arguments.js +2 -2
- package/dist/commands/arguments.js.map +1 -1
- package/dist/commands/context.d.ts +11 -0
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +13 -0
- package/dist/commands/context.js.map +1 -1
- package/dist/contracts.d.ts +1 -1
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/domain/canvas.d.ts +240 -0
- package/dist/domain/canvas.d.ts.map +1 -0
- package/dist/domain/canvas.js +226 -0
- package/dist/domain/canvas.js.map +1 -0
- package/dist/domain/embeds.d.ts +36 -0
- package/dist/domain/embeds.d.ts.map +1 -0
- package/dist/domain/embeds.js +259 -0
- package/dist/domain/embeds.js.map +1 -0
- package/dist/domain/message-query.d.ts +39 -0
- package/dist/domain/message-query.d.ts.map +1 -0
- package/dist/domain/message-query.js +108 -0
- package/dist/domain/message-query.js.map +1 -0
- package/dist/domain/messages.d.ts +89 -13
- package/dist/domain/messages.d.ts.map +1 -1
- package/dist/domain/messages.js.map +1 -1
- package/dist/framework/bot.d.ts +2 -1
- package/dist/framework/bot.d.ts.map +1 -1
- package/dist/framework/bot.js +34 -3
- package/dist/framework/bot.js.map +1 -1
- package/dist/framework/events.d.ts +12 -0
- package/dist/framework/events.d.ts.map +1 -1
- package/dist/framework/events.js.map +1 -1
- package/dist/framework/options.d.ts +2 -0
- package/dist/framework/options.d.ts.map +1 -1
- package/dist/framework/options.js.map +1 -1
- package/dist/framework/rate-limits.d.ts +1 -0
- package/dist/framework/rate-limits.d.ts.map +1 -1
- package/dist/framework/rate-limits.js +18 -8
- package/dist/framework/rate-limits.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/canvas/render.d.ts +3 -0
- package/dist/infrastructure/canvas/render.d.ts.map +1 -0
- package/dist/infrastructure/canvas/render.js +118 -0
- package/dist/infrastructure/canvas/render.js.map +1 -0
- package/dist/infrastructure/canvas/worker.mjs +286 -0
- package/dist/infrastructure/fluxer/payload.d.ts +6 -1
- package/dist/infrastructure/fluxer/payload.d.ts.map +1 -1
- package/dist/infrastructure/fluxer/payload.js +58 -19
- package/dist/infrastructure/fluxer/payload.js.map +1 -1
- package/dist/infrastructure/fluxer/resources/messages.d.ts.map +1 -1
- package/dist/infrastructure/fluxer/resources/messages.js +61 -4
- package/dist/infrastructure/fluxer/resources/messages.js.map +1 -1
- package/dist/infrastructure/fluxer/resources/threads.d.ts.map +1 -1
- package/dist/infrastructure/fluxer/resources/threads.js +9 -0
- package/dist/infrastructure/fluxer/resources/threads.js.map +1 -1
- package/dist/infrastructure/fluxer/transport.d.ts.map +1 -1
- package/dist/infrastructure/fluxer/transport.js +9 -5
- package/dist/infrastructure/fluxer/transport.js.map +1 -1
- package/dist/infrastructure/images/transform.d.ts.map +1 -1
- package/dist/infrastructure/images/transform.js +14 -9
- package/dist/infrastructure/images/transform.js.map +1 -1
- package/dist/infrastructure/process-budget.d.ts +3 -0
- package/dist/infrastructure/process-budget.d.ts.map +1 -0
- package/dist/infrastructure/process-budget.js +17 -0
- package/dist/infrastructure/process-budget.js.map +1 -0
- package/dist/ports/canvas.d.ts +5 -0
- package/dist/ports/canvas.d.ts.map +1 -0
- package/dist/ports/canvas.js +2 -0
- package/dist/ports/canvas.js.map +1 -0
- package/dist/ports/resources/messages.d.ts +17 -7
- package/dist/ports/resources/messages.d.ts.map +1 -1
- package/dist/ports/resources/messages.js.map +1 -1
- package/dist/ports/resources/threads.d.ts +6 -0
- package/dist/ports/resources/threads.d.ts.map +1 -1
- package/dist/ports/resources/threads.js.map +1 -1
- package/dist/scripting/builtins/canvas.d.ts +2 -0
- package/dist/scripting/builtins/canvas.d.ts.map +1 -0
- package/dist/scripting/builtins/canvas.js +118 -0
- package/dist/scripting/builtins/canvas.js.map +1 -0
- package/dist/scripting/builtins/embeds.d.ts +1 -2
- package/dist/scripting/builtins/embeds.d.ts.map +1 -1
- package/dist/scripting/builtins/embeds.js +90 -35
- package/dist/scripting/builtins/embeds.js.map +1 -1
- package/dist/scripting/builtins/index.d.ts.map +1 -1
- package/dist/scripting/builtins/index.js +4 -1
- package/dist/scripting/builtins/index.js.map +1 -1
- package/dist/scripting/builtins/language/objects.d.ts.map +1 -1
- package/dist/scripting/builtins/language/objects.js +2 -1
- package/dist/scripting/builtins/language/objects.js.map +1 -1
- package/dist/scripting/builtins/language/state.d.ts.map +1 -1
- package/dist/scripting/builtins/language/state.js +14 -9
- package/dist/scripting/builtins/language/state.js.map +1 -1
- package/dist/scripting/builtins/messages.js +3 -3
- package/dist/scripting/builtins/messages.js.map +1 -1
- package/dist/scripting/builtins/native-expressions.d.ts.map +1 -1
- package/dist/scripting/builtins/native-expressions.js +3 -1
- package/dist/scripting/builtins/native-expressions.js.map +1 -1
- package/dist/scripting/builtins/native-messages.d.ts.map +1 -1
- package/dist/scripting/builtins/native-messages.js +17 -0
- package/dist/scripting/builtins/native-messages.js.map +1 -1
- package/dist/scripting/builtins/native-threads.d.ts.map +1 -1
- package/dist/scripting/builtins/native-threads.js +8 -0
- package/dist/scripting/builtins/native-threads.js.map +1 -1
- package/dist/scripting/builtins/payload.d.ts +4 -1
- package/dist/scripting/builtins/payload.d.ts.map +1 -1
- package/dist/scripting/builtins/payload.js +127 -5
- package/dist/scripting/builtins/payload.js.map +1 -1
- package/dist/scripting/builtins/resource-extras.d.ts.map +1 -1
- package/dist/scripting/builtins/resource-extras.js +10 -2
- package/dist/scripting/builtins/resource-extras.js.map +1 -1
- package/dist/scripting/canvas-execution.d.ts +12 -0
- package/dist/scripting/canvas-execution.d.ts.map +1 -0
- package/dist/scripting/canvas-execution.js +14 -0
- package/dist/scripting/canvas-execution.js.map +1 -0
- package/dist/scripting/evaluator.d.ts +3 -0
- package/dist/scripting/evaluator.d.ts.map +1 -1
- package/dist/scripting/evaluator.js +45 -25
- package/dist/scripting/evaluator.js.map +1 -1
- package/dist/services/attachments.d.ts.map +1 -1
- package/dist/services/attachments.js +6 -4
- package/dist/services/attachments.js.map +1 -1
- package/dist/services/canvas.d.ts +43 -0
- package/dist/services/canvas.d.ts.map +1 -0
- package/dist/services/canvas.js +587 -0
- package/dist/services/canvas.js.map +1 -0
- package/dist/services/http.d.ts.map +1 -1
- package/dist/services/http.js +34 -44
- package/dist/services/http.js.map +1 -1
- package/dist/services/resource-authorization.d.ts.map +1 -1
- package/dist/services/resource-authorization.js +37 -6
- package/dist/services/resource-authorization.js.map +1 -1
- package/docs/API.md +13 -2
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/BENCHMARKS.md +35 -0
- package/docs/BOT-BASES.md +168 -0
- package/docs/CANVAS.md +274 -0
- package/docs/CLI.md +26 -3
- package/docs/EMBEDS.md +153 -0
- package/docs/FUNCTION-GAPS.md +7 -6
- package/docs/FUNCTIONS.md +41 -6
- package/docs/HTTP.md +18 -0
- package/docs/IMAGES.md +13 -8
- package/docs/LANGUAGE.md +37 -0
- package/docs/MUSIC.md +3 -3
- package/docs/NATIVE.md +36 -3
- package/docs/PARITY-MATRIX.md +952 -0
- package/docs/PARITY.md +26 -10
- package/docs/PLAN.md +40 -1
- package/docs/QUICKSTART.md +18 -2
- package/docs/README.md +7 -2
- package/docs/STORAGE.md +3 -1
- package/docs/VALIDATION.md +55 -0
- package/editors/vscode/functions.json +248 -8
- package/editors/vscode/package.json +1 -1
- package/examples/canvas/fixtures/avatar.png +0 -0
- package/examples/canvas/functions/profile.yuzuha +15 -0
- package/examples/canvas/functions/ranking.yuzuha +46 -0
- package/examples/canvas/functions/welcome.yuzuha +10 -0
- package/examples/canvas/output/function-profile.png +0 -0
- package/examples/canvas/output/function-ranking.png +0 -0
- package/examples/canvas/output/function-welcome.png +0 -0
- package/examples/canvas/output/js-profile.png +0 -0
- package/examples/canvas/output/js-ranking.png +0 -0
- package/examples/canvas/output/js-welcome.png +0 -0
- package/examples/canvas/output/profile.png +0 -0
- package/examples/canvas/output/ranking.png +0 -0
- package/examples/canvas/output/welcome.png +0 -0
- package/examples/canvas/profile.d.mts +3 -0
- package/examples/canvas/profile.mjs +20 -0
- package/examples/canvas/profile.ts +34 -0
- package/examples/canvas/ranking.d.mts +5 -0
- package/examples/canvas/ranking.mjs +25 -0
- package/examples/canvas/ranking.ts +40 -0
- package/examples/canvas/render.ts +48 -0
- package/examples/canvas/welcome.d.mts +3 -0
- package/examples/canvas/welcome.mjs +14 -0
- package/examples/canvas/welcome.ts +27 -0
- package/examples/embeds/complete-embed-functions.ts +31 -0
- package/examples/embeds/complete-embed.ts +33 -0
- package/package.json +16 -5
- package/src/canvas.ts +20 -0
- package/src/cli/arguments.ts +26 -7
- package/src/cli/bot-template-catalog.ts +23 -0
- package/src/cli/bot-template-commands.ts +357 -0
- package/src/cli/bot-template-content.ts +66 -0
- package/src/cli/bot-template-feature-tests.ts +159 -0
- package/src/cli/bot-template-tests.ts +68 -0
- package/src/cli/bot-templates.ts +155 -0
- package/src/cli/main.ts +7 -1
- package/src/cli/scaffold.ts +29 -8
- package/src/cli.ts +1 -1
- package/src/commands/arguments.ts +3 -3
- package/src/commands/context.ts +15 -0
- package/src/contracts.ts +1 -1
- package/src/domain/canvas.ts +259 -0
- package/src/domain/embeds.ts +218 -0
- package/src/domain/message-query.ts +142 -0
- package/src/domain/messages.ts +89 -4
- package/src/framework/bot.ts +30 -5
- package/src/framework/events.ts +12 -0
- package/src/framework/options.ts +2 -0
- package/src/framework/rate-limits.ts +16 -7
- package/src/index.ts +5 -3
- package/src/infrastructure/canvas/render.ts +100 -0
- package/src/infrastructure/canvas/worker.mjs +286 -0
- package/src/infrastructure/fluxer/payload.ts +54 -13
- package/src/infrastructure/fluxer/resources/messages.ts +62 -5
- package/src/infrastructure/fluxer/resources/threads.ts +9 -0
- package/src/infrastructure/fluxer/transport.ts +9 -5
- package/src/infrastructure/images/transform.ts +13 -8
- package/src/infrastructure/process-budget.ts +17 -0
- package/src/ports/canvas.ts +5 -0
- package/src/ports/resources/messages.ts +17 -7
- package/src/ports/resources/threads.ts +7 -0
- package/src/scripting/builtins/canvas.ts +117 -0
- package/src/scripting/builtins/embeds.ts +87 -28
- package/src/scripting/builtins/index.ts +4 -1
- package/src/scripting/builtins/language/objects.ts +2 -1
- package/src/scripting/builtins/language/state.ts +14 -7
- package/src/scripting/builtins/messages.ts +3 -3
- package/src/scripting/builtins/native-expressions.ts +3 -1
- package/src/scripting/builtins/native-messages.ts +17 -0
- package/src/scripting/builtins/native-threads.ts +7 -0
- package/src/scripting/builtins/payload.ts +121 -6
- package/src/scripting/builtins/resource-extras.ts +9 -2
- package/src/scripting/canvas-execution.ts +23 -0
- package/src/scripting/evaluator.ts +25 -9
- package/src/services/attachments.ts +6 -4
- package/src/services/canvas.ts +498 -0
- package/src/services/http.ts +26 -33
- package/src/services/resource-authorization.ts +37 -6
package/CHANGELOG.md
CHANGED
|
@@ -21,6 +21,50 @@ documentos. Veja a [política completa](VERSIONING.md).
|
|
|
21
21
|
|
|
22
22
|
</details>
|
|
23
23
|
|
|
24
|
+
## v0.2.0 · 02/11/2026
|
|
25
|
+
|
|
26
|
+
Embeds completos em uma API só, nos modos nativo e function mode, com uma matriz automática de paridade com o SDK. Esta atualização da biblioteca Yuzuha foi preparada em 02/11/2026 (v0.2.0); a tag Git `v0.2.0` aponta para esta versão.
|
|
27
|
+
|
|
28
|
+
- `Embed` aceita `url`, `timestamp`, `author` com ícone e link, `footer.iconURL`, texto alternativo em imagem e miniatura, e `fields[].inline` opcional. Na função `$color` e em `$embedFromObject`, a cor aceita `#RRGGBB`, tupla `r,g,b` ou nome simples; o tipo `Embed` nativo continua recebendo número. `embed()` valida um embed tipado na API nativa e `yuzuha/sdk` continua expondo o `EmbedBuilder` do SDK.
|
|
29
|
+
- Mensagens aceitam até 10 embeds, `tts`, `stickerIds`, `flags`, `allowedMentions` e `reply` na API nativa. O padrão continua sem menções e sem ping ao autor respondido. Relaxar menções exige `MentionEveryone` do autor, e TTS exige `SendTtsMessages`.
|
|
30
|
+
- Catorze funções novas: `$url`, `$embedTimestamp`, `$author`, `$footerIcon`, `$imageAlt`, `$thumbnailAlt`, `$fields`, `$addField`, `$removeField`, `$editField`, `$embedFromObject`, `$embeds`, `$addEmbed` e `$messageOptions`. `$field` aceita valor vazio quando é inline.
|
|
31
|
+
- `$fetchMessage` e `$messages` devolvem `embeds` normalizados, com `type`, `provider`, `video`, `audio`, `nsfw` e `children` somente leitura.
|
|
32
|
+
- Mudança incompatível: `MessageInfo.embeds` é obrigatório para implementações próprias de `MessagesResources`. Objetos de mensagem em script rejeitam chaves desconhecidas, que antes viravam embed sem validação. Veja [VERSIONING.md](VERSIONING.md#migrar-para-020).
|
|
33
|
+
- `npm run docs:generate` gera [PARITY-MATRIX.md](docs/PARITY-MATRIX.md), que classifica cada export do SDK como coberto por script, coberto pelo código nativo, só-SDK ou lacuna. Um teste falha quando o SDK ganha export sem área.
|
|
34
|
+
- Catálogo do function mode: de 322 para **336** funções. [FUNCTION-GAPS.md](docs/FUNCTION-GAPS.md) foi atualizado com a contagem real.
|
|
35
|
+
|
|
36
|
+
## v0.1.9 · 29/10/2026
|
|
37
|
+
|
|
38
|
+
Composição opcional de cartões para comandos, eventos e function mode, com fontes locais e renderização isolada. Esta atualização da biblioteca Yuzuha foi preparada em 29/10/2026 (v0.1.9).
|
|
39
|
+
|
|
40
|
+
- `yuzuha/canvas` oferece builder tipado para texto, imagens, avatares, formas, gradientes, sombras, badges e progresso. A raiz e o function mode continuam importáveis sem instalar `@napi-rs/canvas`; o backend carrega somente no processo filho durante a renderização.
|
|
41
|
+
- `ctx.canvas.send` e `bot.contextEvent` permitem anexar imagens em comandos e eventos sem mensagem. O canal é explícito quando o evento não o fornece.
|
|
42
|
+
- Doze funções `$canvas*` mantêm cenas privadas por execução e elevam o catálogo canônico de 310 para **322**. Quotas, cancelamento e limites atravessam `$try`.
|
|
43
|
+
- Inter 4.1 Regular e Bold acompanham os arquivos originais e a licença OFL. Fontes próprias podem vir de bytes, aliases configurados ou HTTP submetido à política do contexto.
|
|
44
|
+
- Canvas e Sharp compartilham no máximo dois processos simultâneos, sem fila implícita. Canvas não depende de Sharp; `yuzuha/images` preserva seu contrato.
|
|
45
|
+
- Perfil, boas-vindas e ranking têm versões JS, TS e function mode e geram nove PNGs offline. O tarball verifica imports sem os peers e renderização real com Canvas sem Sharp.
|
|
46
|
+
- SDK 3.3.0, Node >=22.13 e schema persistido 2 permanecem compatíveis.
|
|
47
|
+
|
|
48
|
+
## v0.1.8 · 28/10/2026
|
|
49
|
+
|
|
50
|
+
Bases de bots, buscas e páginas do Fluxer.js, com autorização compartilhada e correções de limites, streams e cooldowns. Esta atualização da biblioteca Yuzuha foi preparada em 28/10/2026 (v0.1.8).
|
|
51
|
+
|
|
52
|
+
- A CLI oferece sete bases JS/TS com `templates` e `init --template`: simple, multifunctional, moderation, community, economy, entertainment e utility. A multifuncional reúne 24 comandos raiz; os projetos incluem configuração, exemplos e testes offline. O scaffold padrão e `--functions` continuam disponíveis.
|
|
53
|
+
- A distribuição preserva o modo executável da CLI e testa a instalação, os tipos e o dispatch dos 14 pares de base/linguagem a partir do tarball.
|
|
54
|
+
- Quatro funções novas levam o catálogo de 306 a **310**: `$searchMessagesAdvanced`, `$pinnedMessagesPage`, `$reactionUsersPage` e `$threadMember`. Seus recursos e tipos também estão disponíveis na API nativa.
|
|
55
|
+
- A busca aceita filtros de conteúdo, frases, autores, canais, menções, anexos, IDs e ordenação sem exigir texto. A validação é compartilhada entre scripts e adaptador, copia arrays e limita as opções a 32 KiB; a busca anterior continua disponível, incluindo cursor vazio.
|
|
56
|
+
- Páginas de fixadas preservam ordem de fixação, timestamps, `hasMore` e cursor ISO. Páginas de reações preservam `hasMore`/`nextAfter`, incluindo respostas legadas em array. A consulta individual de membros de threads inclui flags e metadados de mute, com o autor do contexto como padrão nos scripts.
|
|
57
|
+
- Mutações de emojis e stickers pelo contexto exigem `ManageExpressions` de autor e bot no servidor atual. Criar emoji verifica as permissões antes do download e revalida antes de criar o recurso. Guards não são capturados por `$try`.
|
|
58
|
+
- `$jsonEncode` preserva guards, limites, cancelamento, controle de loops e `PartialModerationError`. Incrementos, remoções/inclusões em arrays e atualizações por caminho verificam a saída antes do commit, preservando valor, TTL e ausência quando recusados.
|
|
59
|
+
- O prazo cooperativo do runtime usa relógio monotônico. Esperas externas sobrepostas ou aninhadas descontam seu intervalo uma única vez, sem conceder tempo duplicado.
|
|
60
|
+
- HTTP valida sub-redes IPv4/IPv6, inclusive IPv4 mapeado, link-local e redes especiais. Literais IPv6 públicos funcionam sem consulta DNS; credenciais na URL e corpos em GET/HEAD são recusados.
|
|
61
|
+
- Redirects preservam os métodos conforme o padrão Fetch e removem cabeçalhos de conteúdo quando descartam o corpo. Respostas binárias copiam chunks reutilizados; cancelamento libera readers mesmo quando a fonte não conclui a limpeza.
|
|
62
|
+
- Anexos por stream mantêm os metadados validados durante a leitura e não deixam um timeout agendado quando a fonte já está bloqueada por outro reader.
|
|
63
|
+
- Deduplicação de mensagens e consultas de cooldown ativo deixam de varrer o mapa de cooldowns. A coleta considera vencimentos e pressão de capacidade; renovação e admissão reutilizam entradas expiradas, mantendo o teto de 100 mil. Flags malformadas geram `GuardError` antes do handler.
|
|
64
|
+
- Um benchmark reproduzível compara a implementação anterior e a atual com amostras intercaladas. O ganho é localizado na manutenção removida; cenários comuns tiveram resultados mistos, registrados sem alegação de aceleração geral.
|
|
65
|
+
- Referências, catálogo do editor, guias e consumidores JS/TS acompanham os novos contratos. O SDK continua fixado em 3.3.0, o schema persistido em 2 e os sete entrypoints permanecem disponíveis.
|
|
66
|
+
- **Adaptação de integrações:** implementações completas próprias de `MessagesResources` devem acrescentar `pinnedPage` e `reactionUsersPage`; `ThreadsResources` deve acrescentar `member`. Comandos antes autorizados apenas pelo bot podem receber `GuardError` nas mutações de expressões. Apesar da numeração patch, esta entrega altera esses contratos; veja [VERSIONING.md](VERSIONING.md) antes de atualizar.
|
|
67
|
+
|
|
24
68
|
## v0.1.7 · 23/10/2026
|
|
25
69
|
|
|
26
70
|
Loops controláveis, comparadores de arrays, regex isolada, decimais exatos e busca pela CLI, com o conteúdo preparado na 0.1.6. Esta atualização da biblioteca Yuzuha foi preparada em 23/10/2026 (v0.1.7).
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Os dois modos compartilham permissões, moderação, estado e recursos.
|
|
|
7
7
|
O Yuzuha usa **Fluxer.js 3.3.0**. Você continua tendo acesso ao client original
|
|
8
8
|
por `bot.client` e aos exports do SDK em `yuzuha/sdk`.
|
|
9
9
|
|
|
10
|
-
[0.
|
|
10
|
+
[0.2.0](CHANGELOG.md) · Node **22.13+** · ESM · [MIT](LICENSE)
|
|
11
11
|
|
|
12
12
|
[Começar](#começar) · [Comandos](#escrever-comandos) · [Recursos](#recursos) · [Testes](#testar-sem-token) · [Documentação](#documentação)
|
|
13
13
|
|
|
@@ -16,7 +16,7 @@ por `bot.client` e aos exports do SDK em `yuzuha/sdk`.
|
|
|
16
16
|
### Criar um bot
|
|
17
17
|
|
|
18
18
|
```sh
|
|
19
|
-
npx yuzuha@0.
|
|
19
|
+
npx yuzuha@0.2.0 init ./meu-bot --ts
|
|
20
20
|
cd meu-bot
|
|
21
21
|
npm install
|
|
22
22
|
npm run check
|
|
@@ -42,7 +42,7 @@ para incluir um comando de exemplo com scripts.
|
|
|
42
42
|
### Usar em um projeto existente
|
|
43
43
|
|
|
44
44
|
```sh
|
|
45
|
-
npm install yuzuha@0.
|
|
45
|
+
npm install yuzuha@0.2.0
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
Use `"type": "module"` no `package.json`. O [guia inicial](docs/QUICKSTART.md)
|
|
@@ -84,7 +84,7 @@ export default script({
|
|
|
84
84
|
});
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
O function mode tem **
|
|
87
|
+
O function mode tem **336 funções** para mensagens, guards, moderação, variáveis,
|
|
88
88
|
JSON, arrays, loops, eventos e agendamentos. O runtime é ativado ao registrar um
|
|
89
89
|
comando com `code` ou um evento de script.
|
|
90
90
|
|
|
@@ -103,6 +103,7 @@ e a [cobertura](docs/PARITY.md).
|
|
|
103
103
|
| Dados | Memória, JSON e SQLite; TTL, transações, limpeza e backup/restauração com simulação |
|
|
104
104
|
| Agendamentos | Tarefas persistentes, cron, fusos IANA, pausa/retomada, histórico e retry |
|
|
105
105
|
| HTTP | Texto, bytes, streaming e multipart, com limites, cancelamento e políticas por comando |
|
|
106
|
+
| Canvas | Cartões com texto, avatares, imagens, gradientes, badges e progresso; peer nativo opcional |
|
|
106
107
|
| Música | Lavalink v4 com plugin e ponte de áudio para Fluxer, recuperação, filas editáveis, loop, seek, volume e filtros |
|
|
107
108
|
| Desenvolvimento | CLI, autocomplete e diagnósticos no VS Code, mocks e relógio controlável para testes |
|
|
108
109
|
|
|
@@ -157,6 +158,7 @@ O [índice completo](docs/README.md) reúne os guias e as referências.
|
|
|
157
158
|
| Programar em JS/TS | [Guia nativo](docs/NATIVE.md), [framework](docs/FRAMEWORK.md) e [API](docs/API.md) |
|
|
158
159
|
| Criar um bot de música | [Lavalink, filas e voz Fluxer](docs/MUSIC.md) |
|
|
159
160
|
| Medir performance | [Benchmarks e comparações com a 0.1.5](docs/BENCHMARKS.md) |
|
|
161
|
+
| Compor cartões e imagens | [Canvas](docs/CANVAS.md) e [transformações de imagem](docs/IMAGES.md) |
|
|
160
162
|
| Escrever scripts `$...` | [Linguagem](docs/LANGUAGE.md) e [referência de funções](docs/FUNCTIONS.md) |
|
|
161
163
|
| Copiar exemplos | [Receitas](docs/COOKBOOK.md) e [código de exemplo](examples) |
|
|
162
164
|
| Usar o editor ou diagnosticar um erro | [VS Code](docs/EDITOR.md) e [problemas comuns](docs/TROUBLESHOOTING.md) |
|
|
@@ -196,3 +198,18 @@ Transformações opcionais de imagens e entrada de anexos por stream estão em
|
|
|
196
198
|
[IMAGES.md](docs/IMAGES.md); consultas por prefixo e cursor em
|
|
197
199
|
[STORAGE.md](docs/STORAGE.md), e limites das integrações em
|
|
198
200
|
[INTEGRATIONS.md](docs/INTEGRATIONS.md).
|
|
201
|
+
|
|
202
|
+
### Bases de bots
|
|
203
|
+
|
|
204
|
+
Sete opções: `simple`, `multifunctional`, `moderation`, `community`, `economy`,
|
|
205
|
+
`entertainment` e `utility`. Na cópia local compilada:
|
|
206
|
+
|
|
207
|
+
```sh
|
|
208
|
+
node dist/cli.js templates
|
|
209
|
+
node dist/cli.js init ../bot-comunidade --template community --ts --local
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
A multifuncional reúne 24 comandos raiz com embeds e subcomandos, incluindo
|
|
213
|
+
moderação com casos, regras, sugestões, enquetes, moedas virtuais, diversão
|
|
214
|
+
e notas pessoais em DM. Todas as bases aceitam JS/TS e `--functions`, com README
|
|
215
|
+
e testes offline próprios. Veja [BOT-BASES.md](docs/BOT-BASES.md).
|
package/VERSIONING.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# Versionamento
|
|
2
2
|
|
|
3
3
|
O Yuzuha aplica o formato Hory ao histórico e usa **SemVer simples** no pacote.
|
|
4
|
-
A versão desta atualização é **0.
|
|
4
|
+
A versão desta atualização é **0.2.0**.
|
|
5
5
|
|
|
6
6
|
## Pacote e histórico
|
|
7
7
|
|
|
8
8
|
| Lugar | Formato nesta versão |
|
|
9
9
|
|---|---|
|
|
10
|
-
| `package.json` e entrada raiz de `package-lock.json` | `0.
|
|
11
|
-
| Pacote npm e saída de `yuzuha --version` | `0.
|
|
12
|
-
| Título do changelog | `## v0.
|
|
13
|
-
|
|
|
10
|
+
| `package.json` e entrada raiz de `package-lock.json` | `0.2.0` |
|
|
11
|
+
| Pacote npm e saída de `yuzuha --version` | `0.2.0` |
|
|
12
|
+
| Título do changelog | `## v0.2.0 · 02/11/2026` |
|
|
13
|
+
| Tag Git | `v0.2.0` |
|
|
14
14
|
|
|
15
15
|
O SDK e a CLI pertencem ao mesmo pacote. Para bibliotecas, a convenção Hory mantém
|
|
16
16
|
SemVer sem `m`, sem seções por superfície e sem sufixos de canal.
|
|
@@ -30,7 +30,8 @@ estivermos em `0.x`. Ao chegar a `1.0.0`, mudanças incompatíveis exigem major;
|
|
|
30
30
|
novas funcionalidades compatíveis, minor; correções compatíveis, patch.
|
|
31
31
|
|
|
32
32
|
Os exports públicos são `yuzuha`, `yuzuha/functions`, `yuzuha/sdk`,
|
|
33
|
-
`yuzuha/testing`, `yuzuha/tooling`, `yuzuha/music
|
|
33
|
+
`yuzuha/testing`, `yuzuha/tooling`, `yuzuha/music`, `yuzuha/images` e
|
|
34
|
+
`yuzuha/canvas`. A organização interna de `src/` não cria estabilidade de deep
|
|
34
35
|
imports. Schema persistido,
|
|
35
36
|
gramática e funções documentadas também fazem parte da compatibilidade.
|
|
36
37
|
|
|
@@ -40,6 +41,77 @@ gerado por `init` pertence ao consumidor e não precisa acompanhar a biblioteca.
|
|
|
40
41
|
|
|
41
42
|
## Preparar uma atualização
|
|
42
43
|
|
|
44
|
+
### Migrar para 0.2.0
|
|
45
|
+
|
|
46
|
+
A 0.2.0 acrescenta campos a `Embed` (`url`, `timestamp`, `author`, `footer.iconURL`,
|
|
47
|
+
alt text em imagem e miniatura), `allowedMentions`, `tts`, `stickerIds`, `flags` e
|
|
48
|
+
`reply` em `Payload`, além de 14 funções de script e a leitura normalizada de embeds
|
|
49
|
+
em `$fetchMessage` e `$messages`. Os exports públicos continuam os mesmos.
|
|
50
|
+
|
|
51
|
+
Há duas mudanças de contrato, por isso a versão é minor na série `0.x`:
|
|
52
|
+
|
|
53
|
+
- `MessageInfo.embeds` passou a ser obrigatório. Quem implementa `MessagesResources`
|
|
54
|
+
própria deve devolver `embeds` (use `[]` se não houver embeds).
|
|
55
|
+
- Objetos de mensagem em script (`$reply`, `$sendMessage`, `$editMessage`) aceitam
|
|
56
|
+
somente as chaves `content`, `embeds`, `tts`, `stickerIds`, `flags` e `allowedMentions`.
|
|
57
|
+
Antes, qualquer objeto virava embed sem validação; agora campos desconhecidos são erro.
|
|
58
|
+
|
|
59
|
+
Menções só relaxam com a permissão `MentionEveryone` do autor, e TTS exige
|
|
60
|
+
`SendTtsMessages`. O padrão continua sem menções e sem ping ao autor respondido.
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
npm install yuzuha@0.2.0
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Migrar para 0.1.9
|
|
67
|
+
|
|
68
|
+
A 0.1.9 acrescenta `yuzuha/canvas`, `ctx.canvas` e `bot.contextEvent`, além de
|
|
69
|
+
12 funções de script da categoria `canvas`. O pacote continua utilizável sem
|
|
70
|
+
Canvas; para renderizar, instale `@napi-rs/canvas@^1.0.13`. Sem o peer, somente
|
|
71
|
+
a chamada de renderização falha com `CANVAS_DEPENDENCY`. Sharp continua sendo
|
|
72
|
+
opcional e independente. O envio usa `resources.messages.sendBytes` e eventos
|
|
73
|
+
sem canal precisam fornecer `channelID` em `ctx.canvas.send`.
|
|
74
|
+
|
|
75
|
+
`CanvasConfig` pode registrar bytes de assets e fontes TTF/OTF. As respostas
|
|
76
|
+
HTTP continuam sujeitas à política e ao limite configurado no bot. Canvas e
|
|
77
|
+
transformações Sharp compartilham duas vagas de processo. O schema persistido
|
|
78
|
+
permanece em 2 e o SDK em 3.3.0; não há migração de dados.
|
|
79
|
+
|
|
80
|
+
```sh
|
|
81
|
+
npm install yuzuha@0.1.9 @napi-rs/canvas@^1.0.13
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Veja [CANVAS.md](docs/CANVAS.md) para opções, limites, fontes e exemplos. A
|
|
85
|
+
extensão incluída acompanha a versão 0.1.9.
|
|
86
|
+
|
|
87
|
+
### Migrar para 0.1.8
|
|
88
|
+
|
|
89
|
+
A 0.1.8 é uma exceção pontual à regra de versões minor para mudanças de
|
|
90
|
+
contrato na série 0.x. Embora use numeração patch, requer adaptação de
|
|
91
|
+
implementações completas próprias de `Resources` e revisão das autorizações
|
|
92
|
+
de comandos. A regra de compatibilidade acima continua valendo para as
|
|
93
|
+
próximas versões.
|
|
94
|
+
|
|
95
|
+
- Acrescente `messages.pinnedPage`, `messages.reactionUsersPage` e
|
|
96
|
+
`threads.member` aos adaptadores completos. Os tipos de retorno são
|
|
97
|
+
`PinnedMessagesPage`, `ReactionUsersPage` e `ThreadMemberDetails`, exportados
|
|
98
|
+
pela raiz. `mockResources` continua aceitando overrides parciais.
|
|
99
|
+
- Mutações de emojis/stickers por `ctx.resources.expressions` exigem
|
|
100
|
+
`ManageExpressions` de autor e bot no servidor do contexto. Código confiável
|
|
101
|
+
que precisa operar diretamente com a autoridade do bot continua usando
|
|
102
|
+
`bot.resources` ou `bot.client` explicitamente.
|
|
103
|
+
- HTTP recusa credenciais embutidas na URL, corpos GET/HEAD e destinos nas
|
|
104
|
+
redes locais/especiais bloqueadas, incluindo IPv4 mapeado em IPv6. Use
|
|
105
|
+
`Authorization` para autenticação; rede privada exige `allowPrivate: true`
|
|
106
|
+
explícito. Redirects 301/302 preservam PUT/PATCH/DELETE e 303 preserva HEAD;
|
|
107
|
+
cabeçalhos de conteúdo são removidos quando o corpo é descartado.
|
|
108
|
+
- As opções de busca recebem validação compartilhada de tipos, IDs, cursores
|
|
109
|
+
e limites. Texto é opcional na API nativa e em `$searchMessagesAdvanced`;
|
|
110
|
+
`$searchMessages` mantém sua assinatura e aceita cursor vazio.
|
|
111
|
+
- O catálogo passa a 310 funções. Imports, SDK 3.3.0 e schema 2 permanecem;
|
|
112
|
+
não há migração de dados em disco. As sete bases da CLI são aditivas e não
|
|
113
|
+
reescrevem projetos existentes. A extensão incluída acompanha a versão 0.1.8.
|
|
114
|
+
|
|
43
115
|
### Migrar para 0.1.7
|
|
44
116
|
|
|
45
117
|
A distribuição 0.1.7 inclui o conteúdo preparado na 0.1.6 e acrescenta
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Copyright (c) 2016 The Inter Project Authors (https://github.com/rsms/inter)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
-----------------------------------------------------------
|
|
8
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
9
|
+
-----------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
PREAMBLE
|
|
12
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
13
|
+
development of collaborative font projects, to support the font creation
|
|
14
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
15
|
+
open framework in which fonts may be shared and improved in partnership
|
|
16
|
+
with others.
|
|
17
|
+
|
|
18
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
19
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
20
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
21
|
+
redistributed and/or sold with any software provided that any reserved
|
|
22
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
23
|
+
however, cannot be released under any other type of license. The
|
|
24
|
+
requirement for fonts to remain under this license does not apply
|
|
25
|
+
to any document created using the fonts or their derivatives.
|
|
26
|
+
|
|
27
|
+
DEFINITIONS
|
|
28
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
29
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
30
|
+
include source files, build scripts and documentation.
|
|
31
|
+
|
|
32
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
33
|
+
copyright statement(s).
|
|
34
|
+
|
|
35
|
+
"Original Version" refers to the collection of Font Software components as
|
|
36
|
+
distributed by the Copyright Holder(s).
|
|
37
|
+
|
|
38
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
39
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
40
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
41
|
+
new environment.
|
|
42
|
+
|
|
43
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
44
|
+
writer or other person who contributed to the Font Software.
|
|
45
|
+
|
|
46
|
+
PERMISSION AND CONDITIONS
|
|
47
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
48
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
49
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
50
|
+
Software, subject to the following conditions:
|
|
51
|
+
|
|
52
|
+
1) Neither the Font Software nor any of its individual components,
|
|
53
|
+
in Original or Modified Versions, may be sold by itself.
|
|
54
|
+
|
|
55
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
56
|
+
redistributed and/or sold with any software, provided that each copy
|
|
57
|
+
contains the above copyright notice and this license. These can be
|
|
58
|
+
included either as stand-alone text files, human-readable headers or
|
|
59
|
+
in the appropriate machine-readable metadata fields within text or
|
|
60
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
61
|
+
|
|
62
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
63
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
64
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
65
|
+
presented to the users.
|
|
66
|
+
|
|
67
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
68
|
+
Software shall not be used to promote, endorse or advertise any
|
|
69
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
70
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
71
|
+
permission.
|
|
72
|
+
|
|
73
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
74
|
+
must be distributed entirely under this license, and must not be
|
|
75
|
+
distributed under any other license. The requirement for fonts to
|
|
76
|
+
remain under this license does not apply to any document created
|
|
77
|
+
using the Font Software.
|
|
78
|
+
|
|
79
|
+
TERMINATION
|
|
80
|
+
This license becomes null and void if any of the above conditions are
|
|
81
|
+
not met.
|
|
82
|
+
|
|
83
|
+
DISCLAIMER
|
|
84
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
85
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
86
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
87
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
88
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
89
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
90
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
91
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
92
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
These unmodified font files are from Inter 4.1, distributed by the upstream
|
|
2
|
+
Inter project under the SIL Open Font License 1.1.
|
|
3
|
+
|
|
4
|
+
- `Inter-Regular.ttf`: Inter 4.1 Regular
|
|
5
|
+
- `Inter-Bold.ttf`: Inter 4.1 Bold
|
|
6
|
+
- License text: `OFL.txt`
|
|
7
|
+
- Upstream release: https://github.com/rsms/inter/releases/tag/v4.1
|
|
8
|
+
- License source: https://github.com/rsms/inter/blob/v4.1/LICENSE.txt
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { arch, cpus, platform } from 'node:os';
|
|
5
|
+
import { performance } from 'node:perf_hooks';
|
|
6
|
+
import { RateLimits } from '../dist/framework/rate-limits.js';
|
|
7
|
+
import { YuzuhaError } from '../dist/errors.js';
|
|
8
|
+
|
|
9
|
+
// Baseline: src/framework/rate-limits.ts at a227759f726420471ade044a3cf9600a6359a668, with TypeScript types removed.
|
|
10
|
+
class BaselineRateLimits {
|
|
11
|
+
now;
|
|
12
|
+
seen = new Map();
|
|
13
|
+
seenKeys = [];
|
|
14
|
+
seenExpirations = [];
|
|
15
|
+
seenCursor = 0;
|
|
16
|
+
cooldowns = new Map();
|
|
17
|
+
nextSweep = 0;
|
|
18
|
+
|
|
19
|
+
constructor(now = Date.now) { this.now = now; }
|
|
20
|
+
|
|
21
|
+
sweep(time) {
|
|
22
|
+
if (time < this.nextSweep) return;
|
|
23
|
+
for (const [key, until] of this.cooldowns) if (until <= time) this.cooldowns.delete(key);
|
|
24
|
+
this.nextSweep = time + 1000;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
duplicate(channelID, messageID) {
|
|
28
|
+
const time = this.now();
|
|
29
|
+
this.sweep(time);
|
|
30
|
+
const key = `${channelID.length}:${channelID}${messageID}`;
|
|
31
|
+
if ((this.seen.get(key) ?? 0) > time) return true;
|
|
32
|
+
const previous = this.seenKeys[this.seenCursor];
|
|
33
|
+
if (previous !== undefined && this.seen.get(previous) === this.seenExpirations[this.seenCursor]) this.seen.delete(previous);
|
|
34
|
+
const until = time + 60_000;
|
|
35
|
+
this.seen.set(key, until);
|
|
36
|
+
this.seenKeys[this.seenCursor] = key; this.seenExpirations[this.seenCursor] = until;
|
|
37
|
+
this.seenCursor = (this.seenCursor + 1) % 10_000;
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
cooldown(key, duration) {
|
|
42
|
+
const time = this.now();
|
|
43
|
+
this.sweep(time);
|
|
44
|
+
const remaining = (this.cooldowns.get(key) ?? 0) - time;
|
|
45
|
+
if (remaining > 0) return remaining;
|
|
46
|
+
if (this.cooldowns.size >= 100_000) throw new YuzuhaError('COOLDOWN_CAPACITY', 'Capacidade de cooldown excedida.');
|
|
47
|
+
this.cooldowns.set(key, time + duration);
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const config = { samples: 7, normalIterations: 50_000, loadedIterations: 1000, entries: 25_000,
|
|
53
|
+
warmup: 2000, normalClockStepMs: 0, loadedClockStepMs: 1000, cooldownMs: 1_000_000_000_000 };
|
|
54
|
+
let json = false;
|
|
55
|
+
for (let index = 2; index < process.argv.length; index++) {
|
|
56
|
+
const option = process.argv[index];
|
|
57
|
+
if (option === '--json') { json = true; continue; }
|
|
58
|
+
const name = { '--samples': 'samples', '--normal-iterations': 'normalIterations', '--loaded-iterations': 'loadedIterations', '--entries': 'entries' }[option];
|
|
59
|
+
const value = Number(process.argv[++index]);
|
|
60
|
+
const max = { samples: 50, normalIterations: 90_000, loadedIterations: 100_000, entries: 100_000 }[name];
|
|
61
|
+
if (!max || !Number.isSafeInteger(value) || value < 1 || value > max) throw new Error(`Opção inválida: ${option}.`);
|
|
62
|
+
config[name] = value;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const scenarios = [
|
|
66
|
+
{ name: 'duplicate/same-tick', operation: 'duplicate', loaded: false },
|
|
67
|
+
{ name: 'cooldown/new-same-tick', operation: 'new', loaded: false },
|
|
68
|
+
{ name: 'cooldown/active-same-tick', operation: 'active', loaded: false },
|
|
69
|
+
{ name: 'duplicate/loaded-clock-steps', operation: 'duplicate', loaded: true },
|
|
70
|
+
{ name: 'cooldown/loaded-clock-steps', operation: 'active', loaded: true },
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
function fixture(Implementation, scenario, iterations) {
|
|
74
|
+
let now = 0;
|
|
75
|
+
const limits = new Implementation(() => now);
|
|
76
|
+
const step = scenario.loaded ? config.loadedClockStepMs : config.normalClockStepMs;
|
|
77
|
+
if (scenario.loaded) for (let index = 0; index < config.entries; index++) limits.cooldown(String(index), config.cooldownMs);
|
|
78
|
+
else if (scenario.operation === 'active') limits.cooldown('0', config.cooldownMs);
|
|
79
|
+
const outputs = new Array(iterations);
|
|
80
|
+
return {
|
|
81
|
+
run() {
|
|
82
|
+
for (let index = 0; index < iterations; index++) {
|
|
83
|
+
now += step;
|
|
84
|
+
outputs[index] = scenario.operation === 'duplicate' ? limits.duplicate('channel', String(index))
|
|
85
|
+
: limits.cooldown(scenario.operation === 'active' ? '0' : String(index), config.cooldownMs);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
validate() {
|
|
89
|
+
for (let index = 0; index < iterations; index++) {
|
|
90
|
+
const expected = scenario.operation === 'duplicate' ? false
|
|
91
|
+
: scenario.operation === 'active' ? config.cooldownMs - step * (index + 1) : 0;
|
|
92
|
+
assert.equal(outputs[index], expected);
|
|
93
|
+
}
|
|
94
|
+
return outputs;
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const median = values => [...values].sort((a, b) => a - b)[Math.ceil(values.length / 2) - 1];
|
|
100
|
+
const summarize = (samplesMs, iterations) => ({ samplesMs, medianMs: median(samplesMs),
|
|
101
|
+
operationsPerSecond: iterations * samplesMs.length / (samplesMs.reduce((sum, value) => sum + value, 0) / 1000) });
|
|
102
|
+
const implementations = [['baseline', BaselineRateLimits], ['current', RateLimits]];
|
|
103
|
+
const results = [];
|
|
104
|
+
for (const scenario of scenarios) {
|
|
105
|
+
const iterations = scenario.loaded ? config.loadedIterations : config.normalIterations;
|
|
106
|
+
for (const [, Implementation] of implementations) {
|
|
107
|
+
const warmup = fixture(Implementation, scenario, Math.min(config.warmup, iterations));
|
|
108
|
+
warmup.run(); warmup.validate();
|
|
109
|
+
}
|
|
110
|
+
const samples = { baseline: [], current: [] };
|
|
111
|
+
for (let sample = 0; sample < config.samples; sample++) {
|
|
112
|
+
const outputs = {};
|
|
113
|
+
for (const [name, Implementation] of sample % 2 ? [...implementations].reverse() : implementations) {
|
|
114
|
+
const trial = fixture(Implementation, scenario, iterations);
|
|
115
|
+
global.gc?.();
|
|
116
|
+
const start = performance.now();
|
|
117
|
+
trial.run();
|
|
118
|
+
samples[name].push(performance.now() - start);
|
|
119
|
+
outputs[name] = trial.validate();
|
|
120
|
+
}
|
|
121
|
+
assert.deepEqual(outputs.current, outputs.baseline);
|
|
122
|
+
}
|
|
123
|
+
const baseline = summarize(samples.baseline, iterations), current = summarize(samples.current, iterations);
|
|
124
|
+
results.push({ name: scenario.name, iterations, entries: scenario.loaded ? config.entries : scenario.operation === 'active' ? 1 : 0,
|
|
125
|
+
clockStepMs: scenario.loaded ? config.loadedClockStepMs : config.normalClockStepMs, baseline, current,
|
|
126
|
+
medianChangePercent: (current.medianMs / baseline.medianMs - 1) * 100 });
|
|
127
|
+
}
|
|
128
|
+
const hash = input => createHash('sha256').update(input).digest('hex');
|
|
129
|
+
const report = { suite: 'rate-limits', date: new Date().toISOString(), node: process.versions.node, platform: platform(), arch: arch(),
|
|
130
|
+
cpu: cpus()[0]?.model, gc: typeof global.gc === 'function', baselineCommit: 'a227759f726420471ade044a3cf9600a6359a668',
|
|
131
|
+
sourceHashes: { baselineImplementation: hash(BaselineRateLimits.toString()), currentDist: hash(await readFile(new URL('../dist/framework/rate-limits.js', import.meta.url))),
|
|
132
|
+
benchmark: hash(await readFile(new URL(import.meta.url))) }, config,
|
|
133
|
+
scope: 'Local synthetic workloads; advancing the fake clock simulates sweep boundaries, not wall-clock throughput of a bot.', results };
|
|
134
|
+
console.log(json ? JSON.stringify(report, null, 2) : [
|
|
135
|
+
`RateLimits · Node ${report.node} · ${report.cpu} · ${report.platform}/${report.arch}`,
|
|
136
|
+
report.scope,
|
|
137
|
+
...results.map(row => `${row.name}: ${row.baseline.medianMs.toFixed(3)} -> ${row.current.medianMs.toFixed(3)} ms; ${row.iterations} operations; clock +${row.clockStepMs} ms/operation`),
|
|
138
|
+
].join('\n'));
|