@omnizap-system/omnizap 2.6.0 → 2.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +58 -13
- package/.github/workflows/ci.yml +5 -5
- package/.github/workflows/codeql.yml +1 -1
- package/.github/workflows/db-migration-check.yml +2 -2
- package/.github/workflows/dependency-review.yml +1 -1
- package/.github/workflows/deploy.yml +2 -2
- package/.github/workflows/release.yml +2 -2
- package/.github/workflows/security-attest-provenance.yml +2 -2
- package/.github/workflows/security-gitleaks.yml +13 -4
- package/.github/workflows/security-runner-hardening.yml +2 -2
- package/.github/workflows/security-scorecard.yml +1 -1
- package/.github/workflows/security-zap-baseline.yml +1 -1
- package/.github/workflows/security-zap-full-scan.yml +2 -1
- package/.github/workflows/security-zizmor.yml +1 -1
- package/.github/workflows/wiki-sync.yml +1 -1
- package/.gitleaksignore +9 -0
- package/CODE_OF_CONDUCT.md +2 -2
- package/GEMINI.md +64 -0
- package/README.md +52 -82
- package/SECURITY.md +1 -1
- package/app/config/index.js +2 -0
- package/app/configParts/adminIdentity.js +5 -5
- package/app/configParts/baileysConfig.js +230 -58
- package/app/configParts/groupUtils.js +5 -0
- package/app/configParts/messagePersistenceService.js +145 -4
- package/app/configParts/sessionConfig.js +157 -0
- package/app/connection/baileysCompatibility.test.js +1 -1
- package/app/connection/groupOwnerWriteStateResolver.js +109 -0
- package/app/connection/socketController.js +660 -158
- package/app/connection/socketController.multiSession.test.js +108 -0
- package/app/controllers/messageController.js +1 -1
- package/app/controllers/messagePipeline/commandMiddleware.js +12 -10
- package/app/controllers/messagePipeline/conversationMiddleware.js +2 -1
- package/app/controllers/messagePipeline/messagePipelineMiddlewares.test.js +104 -0
- package/app/controllers/messagePipeline/preProcessingMiddlewares.js +80 -2
- package/app/controllers/messageProcessingPipeline.js +93 -13
- package/app/controllers/messageProcessingPipeline.test.js +200 -0
- package/app/modules/adminModule/AGENT.md +1 -1
- package/app/modules/adminModule/commandConfig.json +3318 -1347
- package/app/modules/adminModule/groupCommandHandlers.js +858 -15
- package/app/modules/adminModule/groupCommandHandlers.test.js +378 -11
- package/app/modules/adminModule/groupWarningRepository.js +152 -0
- package/app/modules/aiModule/AGENT.md +47 -30
- package/app/modules/aiModule/aiConfigRuntime.js +1 -0
- package/app/modules/aiModule/catCommand.js +135 -27
- package/app/modules/aiModule/commandConfig.json +114 -28
- package/app/modules/analyticsModule/messageAnalysisEventRepository.js +54 -6
- package/app/modules/gameModule/AGENT.md +1 -1
- package/app/modules/gameModule/commandConfig.json +29 -0
- package/app/modules/menuModule/AGENT.md +1 -1
- package/app/modules/menuModule/commandConfig.json +45 -10
- package/app/modules/menuModule/menuCatalogService.js +190 -0
- package/app/modules/menuModule/menuCommandUsageRepository.js +109 -0
- package/app/modules/menuModule/menuDynamicService.js +511 -0
- package/app/modules/menuModule/menuDynamicService.test.js +141 -0
- package/app/modules/menuModule/menus.js +36 -5
- package/app/modules/playModule/AGENT.md +10 -5
- package/app/modules/playModule/commandConfig.json +140 -12
- package/app/modules/playModule/playCommand.js +1 -1417
- package/app/modules/playModule/playCommandConstants.js +80 -0
- package/app/modules/playModule/playCommandCore.js +361 -0
- package/app/modules/playModule/playCommandHandlers.js +41 -0
- package/app/modules/playModule/playCommandMediaClient.js +1872 -0
- package/app/modules/playModule/playConfigRuntime.js +245 -4
- package/app/modules/playModule/playModuleCriticalFlows.test.js +152 -0
- package/app/modules/quoteModule/AGENT.md +1 -1
- package/app/modules/quoteModule/commandConfig.json +29 -0
- package/app/modules/quoteModule/quoteCommand.js +3 -2
- package/app/modules/rpgPokemonModule/AGENT.md +1 -1
- package/app/modules/rpgPokemonModule/commandConfig.json +29 -0
- package/app/modules/rpgPokemonModule/rpgBattleCanvasRenderer.js +5 -4
- package/app/modules/rpgPokemonModule/rpgBattleService.test.js +2 -1
- package/app/modules/rpgPokemonModule/rpgPokemonDomain.js +2 -1
- package/app/modules/rpgPokemonModule/rpgPokemonService.js +38 -37
- package/app/modules/rpgPokemonModule/rpgProfileCanvasRenderer.js +4 -3
- package/app/modules/statsModule/AGENT.md +1 -1
- package/app/modules/statsModule/commandConfig.json +58 -0
- package/app/modules/statsModule/rankingCommon.js +5 -4
- package/app/modules/stickerModule/AGENT.md +1 -1
- package/app/modules/stickerModule/addStickerMetadata.js +4 -3
- package/app/modules/stickerModule/commandConfig.json +145 -0
- package/app/modules/stickerModule/stickerCommand.js +1 -1
- package/app/modules/stickerPackModule/AGENT.md +1 -1
- package/app/modules/stickerPackModule/autoPackCollectorService.js +5 -1
- package/app/modules/stickerPackModule/commandConfig.json +29 -0
- package/app/modules/stickerPackModule/semanticThemeClusterService.js +7 -6
- package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +10 -9
- package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +9 -8
- package/app/modules/stickerPackModule/stickerDomainEventConsumerRuntime.js +3 -2
- package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +2 -1
- package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +80 -58
- package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +2 -1
- package/app/modules/stickerPackModule/stickerPackRepository.js +2 -1
- package/app/modules/stickerPackModule/stickerPackScoreSnapshotRuntime.js +5 -4
- package/app/modules/stickerPackModule/stickerPackService.js +13 -6
- package/app/modules/stickerPackModule/stickerStorageService.js +3 -2
- package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +2 -1
- package/app/modules/systemMetricsModule/AGENT.md +1 -1
- package/app/modules/systemMetricsModule/commandConfig.json +29 -0
- package/app/modules/systemMetricsModule/pingCommand.js +6 -5
- package/app/modules/tiktokModule/AGENT.md +1 -1
- package/app/modules/tiktokModule/commandConfig.json +29 -0
- package/app/modules/tiktokModule/tiktokCommand.js +2 -1
- package/app/modules/userModule/AGENT.md +1 -1
- package/app/modules/userModule/commandConfig.json +29 -0
- package/app/modules/userModule/userCommand.js +72 -23
- package/app/modules/waifuPicsModule/AGENT.md +57 -27
- package/app/modules/waifuPicsModule/commandConfig.json +87 -0
- package/app/modules/waifuPicsModule/waifuPicsCommand.js +3 -2
- package/app/observability/metrics.js +136 -0
- package/app/services/ai/commandConfigEnrichmentService.js +229 -47
- package/app/services/ai/conversationRouterService.js +4 -3
- package/app/services/ai/geminiService.js +132 -7
- package/app/services/ai/geminiService.test.js +59 -2
- package/app/services/ai/globalModuleAiHelpService.js +3 -2
- package/app/services/ai/messageCommandExecutionService.js +2 -1
- package/app/services/ai/moduleAiHelpCoreService.js +45 -14
- package/app/services/ai/moduleToolExecutorService.js +3 -2
- package/app/services/ai/moduleToolRegistryService.js +2 -1
- package/app/services/ai/toolCandidateSelectorService.js +6 -5
- package/app/services/auth/googleWebLinkService.js +3 -2
- package/app/services/auth/whatsappLoginLinkService.js +3 -2
- package/app/services/external/pokeApiService.js +4 -3
- package/app/services/group/groupMetadataService.js +24 -1
- package/app/services/infra/dbWriteQueue.js +57 -26
- package/app/services/infra/featureFlagService.js +2 -1
- package/app/services/messaging/captchaService.js +3 -2
- package/app/services/messaging/newsBroadcastService.js +846 -29
- package/app/services/multiSession/assignmentBalancerService.js +457 -0
- package/app/services/multiSession/groupOwnershipRepository.js +381 -0
- package/app/services/multiSession/groupOwnershipService.js +890 -0
- package/app/services/multiSession/groupOwnershipService.test.js +309 -0
- package/app/services/multiSession/sessionRegistryService.js +293 -0
- package/app/services/sticker/stickerFocusService.js +11 -10
- package/app/store/aiPromptStore.js +36 -19
- package/app/store/conversationSessionStore.js +7 -6
- package/app/store/groupConfigStore.js +41 -5
- package/app/store/premiumUserStore.js +21 -7
- package/app/utils/antiLink/antiLinkModule.js +352 -16
- package/app/workers/aiHelperContinuousLearningWorker.js +512 -0
- package/app/workers/aiLearningWorker.js +6 -5
- package/app/workers/commandConfigEnrichmentWorker.js +4 -3
- package/database/index.js +14 -8
- package/database/migrations/20260307_d0_hardening_down.sql +1 -1
- package/database/migrations/20260314_d7_canonical_sender_down.sql +1 -1
- package/database/migrations/20260406_d30_security_analytics_down.sql +1 -1
- package/database/migrations/20260411_d35_group_community_metadata_down.sql +59 -0
- package/database/migrations/20260411_d35_group_community_metadata_up.sql +62 -0
- package/database/migrations/20260412_d36_system_config_tables_down.sql +32 -0
- package/database/migrations/20260412_d36_system_config_tables_up.sql +66 -0
- package/database/migrations/20260413_d37_group_user_warnings_down.sql +11 -0
- package/database/migrations/20260413_d37_group_user_warnings_up.sql +24 -0
- package/database/migrations/20260414_d38_multi_session_foundation_down.sql +72 -0
- package/database/migrations/20260414_d38_multi_session_foundation_up.sql +125 -0
- package/database/migrations/20260414_d39_multi_session_cutover_down.sql +103 -0
- package/database/migrations/20260414_d39_multi_session_cutover_up.sql +83 -0
- package/database/schema.sql +102 -1
- package/docker-compose.yml +4 -1
- package/docs/compliance/acceptable-use-policy-2026-03-07.md +1 -1
- package/docs/compliance/dpa-b2b-standard-2026-03-07.md +1 -1
- package/docs/compliance/privacy-policy-2026-03-07.md +4 -4
- package/docs/security/dsar-lgpd-runbook-2026-03-07.md +1 -1
- package/docs/security/incident-response-lgpd-anpd-runbook-2026-03-07.md +1 -1
- package/docs/security/network-hardening-runbook-2026-03-07.md +53 -0
- package/docs/security/omnizap-static-security-headers.conf +25 -0
- package/docs/wiki/Home.md +1 -1
- package/ecosystem.prod.config.cjs +32 -12
- package/index.js +57 -23
- package/observability/alert-rules.yml +20 -0
- package/observability/grafana/dashboards/omnizap-system-admin.json +229 -0
- package/observability/mysql-setup.sql +4 -4
- package/observability/system-admin-observability.md +26 -0
- package/package.json +20 -6
- package/public/apple-touch-icon.png +0 -0
- package/public/comandos/commands-catalog.json +2853 -3326
- package/public/favicon-16x16.png +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/js/apps/apiDocsApp.js +3 -2
- package/public/js/apps/commandsReactApp.js +280 -99
- package/public/js/apps/createPackApp.js +11 -10
- package/public/js/apps/homeReactApp.js +181 -130
- package/public/js/apps/loginReactApp.js +1 -1
- package/public/js/apps/stickersApp.js +263 -110
- package/public/js/apps/termsReactApp.js +73 -24
- package/public/js/apps/userApp.js +4 -3
- package/public/js/apps/userPasswordResetReactApp.js +406 -0
- package/public/js/apps/userReactApp.js +355 -280
- package/public/js/apps/userSystemAdmReactApp.js +1506 -0
- package/public/pages/api-docs.html +1 -1
- package/public/pages/aup.html +2 -2
- package/public/pages/dpa.html +3 -3
- package/public/pages/licenca.html +4 -4
- package/public/pages/login.html +1 -1
- package/public/pages/notice-and-takedown.html +2 -2
- package/public/pages/politica-de-privacidade.html +6 -6
- package/public/pages/seo-bot-whatsapp-para-grupo.html +3 -3
- package/public/pages/seo-bot-whatsapp-sem-programar.html +3 -3
- package/public/pages/seo-como-automatizar-avisos-no-whatsapp.html +3 -3
- package/public/pages/seo-como-criar-comandos-whatsapp.html +3 -3
- package/public/pages/seo-como-evitar-spam-no-whatsapp.html +3 -3
- package/public/pages/seo-como-moderar-grupo-whatsapp.html +3 -3
- package/public/pages/seo-como-organizar-comunidade-whatsapp.html +3 -3
- package/public/pages/seo-melhor-bot-whatsapp-para-grupos.html +3 -3
- package/public/pages/stickers-admin.html +1 -1
- package/public/pages/stickers-create.html +1 -1
- package/public/pages/stickers.html +6 -6
- package/public/pages/suboperadores.html +2 -2
- package/public/pages/termos-de-uso-texto-integral.html +6 -6
- package/public/pages/termos-de-uso.html +3 -3
- package/public/pages/user-password-reset.html +4 -5
- package/public/pages/user-systemadm.html +9 -463
- package/public/pages/user.html +2 -2
- package/scripts/clear-whatsapp-session.sh +123 -0
- package/scripts/core-ai-mode.mjs +163 -0
- package/scripts/deploy.sh +11 -1
- package/scripts/email-broadcast-terms-update.mjs +2 -1
- package/scripts/enrich-command-config-ux-openai.mjs +492 -0
- package/scripts/generate-commands-catalog.mjs +166 -2
- package/scripts/generate-module-agents.mjs +2 -1
- package/scripts/generate-seo-satellite-pages.mjs +5 -4
- package/scripts/github-deploy-notify.mjs +2 -1
- package/scripts/github-release-notify.mjs +25 -10
- package/scripts/new-whatsapp-session.sh +317 -0
- package/scripts/release.sh +2 -19
- package/scripts/security-smoketest.mjs +6 -5
- package/scripts/security-web-surface-check.mjs +218 -0
- package/scripts/sticker-catalog-loadtest.mjs +5 -4
- package/server/auth/googleWebAuth/googleWebAuthService.js +8 -7
- package/server/auth/jwt/webJwtService.js +1 -1
- package/server/auth/stickerCatalogAuthContext.js +2 -1
- package/server/auth/termsAcceptance/termsAcceptanceHandler.js +2 -1
- package/server/auth/userPassword/userPasswordAuthService.js +2 -1
- package/server/auth/userPassword/userPasswordRecoveryService.js +4 -3
- package/server/auth/webAccount/webAccountHandlers.js +9 -10
- package/server/controllers/admin/adminPanelHandlers.js +267 -16
- package/server/controllers/admin/systemAdminController.js +267 -0
- package/server/controllers/seo/stickerCatalogSeoContext.js +10 -9
- package/server/controllers/sticker/nonCatalogHandlers.js +2 -1
- package/server/controllers/sticker/stickerCatalogController.js +23 -36
- package/server/controllers/system/contactController.js +9 -17
- package/server/controllers/system/githubController.js +3 -2
- package/server/controllers/system/stickerCatalogSystemContext.js +41 -19
- package/server/controllers/system/systemController.js +254 -1
- package/server/controllers/system/systemMetricsController.js +2 -1
- package/server/controllers/userController.js +6 -0
- package/server/email/emailTemplateService.js +5 -3
- package/server/http/httpServer.js +11 -6
- package/server/middleware/rateLimit.js +2 -1
- package/server/middleware/securityHeaders.js +20 -1
- package/server/routes/admin/systemAdminRouter.js +6 -0
- package/server/routes/indexRouter.js +30 -6
- package/server/routes/observability/grafanaProxyRouter.js +254 -0
- package/server/routes/static/staticPageRouter.js +27 -1
- package/server/utils/publicContact.js +31 -0
- package/utils/time/timeModule.js +135 -0
- package/utils/time/timeModule.test.js +65 -0
- package/utils/whatsapp/contactEnv.js +39 -0
- package/vite.config.mjs +7 -1
- package/public/assets/images/brand-icon-192.png +0 -0
- package/scripts/sync-readme-snapshot.mjs +0 -133
|
@@ -357,6 +357,35 @@
|
|
|
357
357
|
"schema": "legacy_v1_and_v2",
|
|
358
358
|
"legacy_name": "figurinha",
|
|
359
359
|
"legacy_fields_present": ["descricao", "metodos_de_uso", "permissao_necessaria", "local_de_uso", "informacoes_coletadas", "argumentos", "pre_condicoes", "dependencias_externas", "efeitos_colaterais", "observabilidade", "privacidade", "acesso", "limite_uso_por_plano"]
|
|
360
|
+
},
|
|
361
|
+
"user_experience": {
|
|
362
|
+
"resumo_usuario": "Converte imagem ou vídeo enviado em figurinha para o WhatsApp. Requer login Google e mídia. Disponível para planos comum e premium.",
|
|
363
|
+
"quando_usar": ["Quando você quer transformar uma foto ou vídeo enviada em uma figurinha para compartilhar no chat.", "Quando desejar adicionar texto opcional à figurinha com o texto após o comando.", "Quando usar o atalho <prefix>s para criar rapidamente a figurinha a partir da mídia recebida."],
|
|
364
|
+
"exemplos_reais": [
|
|
365
|
+
{
|
|
366
|
+
"situacao": "Transformar imagem recebida em figurinha (sem texto).",
|
|
367
|
+
"comando": "<prefix>figurinha",
|
|
368
|
+
"resposta_esperada": "Comando executado com sucesso.",
|
|
369
|
+
"variacao": "com imagem anexada."
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
"situacao": "Criar figurinha com texto personalizado.",
|
|
373
|
+
"comando": "<prefix>figurinha Olá amigos",
|
|
374
|
+
"resposta_esperada": "Comando executado com sucesso.",
|
|
375
|
+
"variacao": "texto_extra fornecido."
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
"situacao": "Usar atalho para vídeo e gerar figurinha.",
|
|
379
|
+
"comando": "<prefix>s",
|
|
380
|
+
"resposta_esperada": "Comando executado com sucesso.",
|
|
381
|
+
"variacao": "vídeo anexado."
|
|
382
|
+
}
|
|
383
|
+
],
|
|
384
|
+
"resposta_esperada": ["Comando executado com sucesso.", "Formato de uso inválido. Consulte metodos_de_uso.", "Permissão insuficiente para executar este comando."],
|
|
385
|
+
"erros_comuns_usuario": ["Não há mídia anexada para transformar em figurinha.", "Formato de uso inválido. Use <prefix>figurinha ou <prefix>s.", "Não é possível converter conteúdo NSFW ou não aprovado.", "Você não está logado no Google ou a autenticação falhou."],
|
|
386
|
+
"passos_se_der_erro": ["Verifique se você enviou uma imagem ou vídeo junto ao comando.", "Tente novamente com <prefix>figurinha ou <prefix>s.", "Certifique-se de estar conectado com sua conta Google e que o login esteja ativo."],
|
|
387
|
+
"resumo_usuario_origem": "auto_ia_assistida",
|
|
388
|
+
"resumo_usuario_revisao_pendente": true
|
|
360
389
|
}
|
|
361
390
|
},
|
|
362
391
|
{
|
|
@@ -553,6 +582,35 @@
|
|
|
553
582
|
"schema": "legacy_v1_and_v2",
|
|
554
583
|
"legacy_name": "paraimagem",
|
|
555
584
|
"legacy_fields_present": ["descricao", "metodos_de_uso", "permissao_necessaria", "local_de_uso", "informacoes_coletadas", "argumentos", "pre_condicoes", "dependencias_externas", "efeitos_colaterais", "observabilidade", "privacidade", "acesso", "limite_uso_por_plano"]
|
|
585
|
+
},
|
|
586
|
+
"user_experience": {
|
|
587
|
+
"resumo_usuario": "Converte figurinha (sticker) para imagem ou vídeo, para você salvar/usar fora do WhatsApp. Disponível para planos comum e premium.",
|
|
588
|
+
"quando_usar": ["Quando você recebeu uma figurinha e quer salvá-la como imagem.", "Quando precisa de um vídeo a partir de uma figurinha (quando suportado).", "Quando quer reutilizar a figurinha em outros lugares ou projetos."],
|
|
589
|
+
"exemplos_reais": [
|
|
590
|
+
{
|
|
591
|
+
"situacao": "Você recebeu uma figurinha e quer salvar como imagem.",
|
|
592
|
+
"comando": "<prefix>paraimagem",
|
|
593
|
+
"resposta_esperada": "A imagem da figurinha é gerada e enviada de volta para você.",
|
|
594
|
+
"variacao": "paraimagem."
|
|
595
|
+
},
|
|
596
|
+
{
|
|
597
|
+
"situacao": "Precisa de um vídeo da figurinha (quando suportado).",
|
|
598
|
+
"comando": "<prefix>tovideo",
|
|
599
|
+
"resposta_esperada": "Vídeo da figurinha gerado e enviado.",
|
|
600
|
+
"variacao": "tovideo."
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
"situacao": "Erro ao enviar comando com formato errado.",
|
|
604
|
+
"comando": "<prefix>paraimagem extra",
|
|
605
|
+
"resposta_esperada": "Formato de uso inválido. Consulte metodos_de_uso.",
|
|
606
|
+
"variacao": "erro de formatação."
|
|
607
|
+
}
|
|
608
|
+
],
|
|
609
|
+
"resposta_esperada": ["Imagem ou vídeo gerado a partir da figurinha enviada (quando disponível).", "Mensagens claras de erro se houver problemas de formato, permissão ou conteúdo."],
|
|
610
|
+
"erros_comuns_usuario": ["Formato de comando inválido ou sem figurinha na mensagem.", "Não há figurinha na mensagem para converter.", "Falha de login ou permissão inadequada (Google Login necessário).", "Tentativa de usar o comando sem indicar uma figurinha compatível."],
|
|
611
|
+
"passos_se_der_erro": ["Confirme que você está logado com Google.", "Envie uma figurinha válida e tente novamente com <prefix>paraimagem, <prefix>tovideo ou <prefix>tovid.", "Verifique se o prefixo do bot está correto.", "Se o problema persistir, peça suporte com print da tela e da mensagem recebida."],
|
|
612
|
+
"resumo_usuario_origem": "auto_ia_assistida",
|
|
613
|
+
"resumo_usuario_revisao_pendente": true
|
|
556
614
|
}
|
|
557
615
|
},
|
|
558
616
|
{
|
|
@@ -771,6 +829,35 @@
|
|
|
771
829
|
"schema": "legacy_v1_and_v2",
|
|
772
830
|
"legacy_name": "figurinhatexto",
|
|
773
831
|
"legacy_fields_present": ["descricao", "metodos_de_uso", "permissao_necessaria", "local_de_uso", "informacoes_coletadas", "argumentos", "pre_condicoes", "dependencias_externas", "efeitos_colaterais", "observabilidade", "privacidade", "acesso", "limite_uso_por_plano"]
|
|
832
|
+
},
|
|
833
|
+
"user_experience": {
|
|
834
|
+
"resumo_usuario": "Gera figurinha com texto em tema escuro. Digite o texto (até 80 caracteres, até 4 linhas) e a figurinha é criada.",
|
|
835
|
+
"quando_usar": ["Quando quiser transformar uma frase curta em uma figurinha para compartilhar no chat.", "Para destacar mensagens com estilo visual sem sair do chat."],
|
|
836
|
+
"exemplos_reais": [
|
|
837
|
+
{
|
|
838
|
+
"situacao": "Criar uma figurinha com uma frase curta para cumprimentar.",
|
|
839
|
+
"comando": "<prefix>figurinhatexto Olá, tudo bem?",
|
|
840
|
+
"resposta_esperada": "Figura gerada com o texto: 'Olá, tudo bem?'.",
|
|
841
|
+
"variacao": "<prefix>st Olá, tudo bem?"
|
|
842
|
+
},
|
|
843
|
+
{
|
|
844
|
+
"situacao": "Texto com várias linhas (até 4 linhas).",
|
|
845
|
+
"comando": "<prefix>figurinhatexto Linha 1\\nLinha 2\\nLinha 3\\nLinha 4",
|
|
846
|
+
"resposta_esperada": "Figura criada com o texto: 'Linha 1\\nLinha 2\\nLinha 3\\nLinha 4'.",
|
|
847
|
+
"variacao": "<prefix>st Linha 1\\nLinha 2\\nLinha 3\\nLinha 4."
|
|
848
|
+
},
|
|
849
|
+
{
|
|
850
|
+
"situacao": "Uso rápido com alias.",
|
|
851
|
+
"comando": "<prefix>st Bom dia a todos",
|
|
852
|
+
"resposta_esperada": "Figura gerada com o texto: 'Bom dia a todos'.",
|
|
853
|
+
"variacao": "<prefix>figurinhatexto Bom dia a todos."
|
|
854
|
+
}
|
|
855
|
+
],
|
|
856
|
+
"resposta_esperada": ["Figura criada com sucesso e pronta para enviar no chat.", "Texto da figurinha incorporado ao sticker.", "Comando executado com sucesso."],
|
|
857
|
+
"erros_comuns_usuario": ["Texto com mais de 80 caracteres.", "Não informar o texto após <prefix>figurinhatexto ou <prefix>st.", "Formato de uso inválido (faltou o texto ou usou caractere não suportado).", "Usar mais de 4 linhas."],
|
|
858
|
+
"passos_se_der_erro": ["Verifique o texto informado: até 80 caracteres e até 4 linhas.", "Repita o comando correto, por exemplo: <prefix>figurinhatexto Seu texto aqui.", "Certifique-se de estar conectado com a conta Google, se necessário.", "Se o problema persistir, aguarde alguns minutos e tente novamente ou procure suporte."],
|
|
859
|
+
"resumo_usuario_origem": "auto_ia_assistida",
|
|
860
|
+
"resumo_usuario_revisao_pendente": true
|
|
774
861
|
}
|
|
775
862
|
},
|
|
776
863
|
{
|
|
@@ -989,6 +1076,35 @@
|
|
|
989
1076
|
"schema": "legacy_v1_and_v2",
|
|
990
1077
|
"legacy_name": "figurinhatextobranco",
|
|
991
1078
|
"legacy_fields_present": ["descricao", "metodos_de_uso", "permissao_necessaria", "local_de_uso", "informacoes_coletadas", "argumentos", "pre_condicoes", "dependencias_externas", "efeitos_colaterais", "observabilidade", "privacidade", "acesso", "limite_uso_por_plano"]
|
|
1079
|
+
},
|
|
1080
|
+
"user_experience": {
|
|
1081
|
+
"resumo_usuario": "Crie figurinha com texto em branco em tema claro usando <prefix>figurinhatextobranco ou <prefix>stw.",
|
|
1082
|
+
"quando_usar": ["Quer compartilhar uma mensagem rápida como imagem no chat.", "Precisa de até 80 caracteres, em até 4 linhas.", "Não precisa de opções adicionais ou ajustes de estilo.", "Prefere um atalho curto com <prefix>stw."],
|
|
1083
|
+
"exemplos_reais": [
|
|
1084
|
+
{
|
|
1085
|
+
"situacao": "Frase motivacional.",
|
|
1086
|
+
"comando": "<prefix>figurinhatextobranco Acredite em si mesmo!",
|
|
1087
|
+
"resposta_esperada": "Figurinha criada com o texto 'Acredite em si mesmo!' em tema claro.",
|
|
1088
|
+
"variacao": "<prefix>stw Acredite em si mesmo!"
|
|
1089
|
+
},
|
|
1090
|
+
{
|
|
1091
|
+
"situacao": "Bom dia.",
|
|
1092
|
+
"comando": "<prefix>figurinhatextobranco Bom dia, equipe!",
|
|
1093
|
+
"resposta_esperada": "Figurinha criada com o texto 'Bom dia, equipe!' em tema claro.",
|
|
1094
|
+
"variacao": "<prefix>stw Bom dia, equipe!"
|
|
1095
|
+
},
|
|
1096
|
+
{
|
|
1097
|
+
"situacao": "Quatro linhas.",
|
|
1098
|
+
"comando": "<prefix>figurinhatextobranco Linha 1 Linha 2 Linha 3 Linha 4",
|
|
1099
|
+
"resposta_esperada": "Figurinha criada com o texto em quatro linhas.",
|
|
1100
|
+
"variacao": "<prefix>stw Linha 1 Linha 2 Linha 3 Linha 4."
|
|
1101
|
+
}
|
|
1102
|
+
],
|
|
1103
|
+
"resposta_esperada": ["Comando executado com sucesso."],
|
|
1104
|
+
"erros_comuns_usuario": ["Texto não informado após o comando.", "Texto excede 80 caracteres ou ultrapassa 4 linhas.", "Formato de uso incorreto ou sem o prefixo correto.", "Tentar usar caracteres não suportados."],
|
|
1105
|
+
"passos_se_der_erro": ["Certifique-se de incluir o texto após o comando, ex.: <prefix>figurinhatextobranco Seu texto.", "Verifique o tamanho: até 80 caracteres e até 4 linhas.", "Use o formato correto: <prefix>figurinhatextobranco ou <prefix>stw.", "Tente novamente. Se o erro persistir, copie o comando usado e peça ajuda."],
|
|
1106
|
+
"resumo_usuario_origem": "auto_ia_assistida",
|
|
1107
|
+
"resumo_usuario_revisao_pendente": true
|
|
992
1108
|
}
|
|
993
1109
|
},
|
|
994
1110
|
{
|
|
@@ -1207,6 +1323,35 @@
|
|
|
1207
1323
|
"schema": "legacy_v1_and_v2",
|
|
1208
1324
|
"legacy_name": "figurinhatextopisca",
|
|
1209
1325
|
"legacy_fields_present": ["descricao", "metodos_de_uso", "permissao_necessaria", "local_de_uso", "informacoes_coletadas", "argumentos", "pre_condicoes", "dependencias_externas", "efeitos_colaterais", "observabilidade", "privacidade", "acesso", "limite_uso_por_plano"]
|
|
1326
|
+
},
|
|
1327
|
+
"user_experience": {
|
|
1328
|
+
"resumo_usuario": "Gera figurinha animada de texto piscante com até 80 caracteres (máx. 4 linhas), usando <prefix>figurinhatextopisca ou <prefix>stb.",
|
|
1329
|
+
"quando_usar": ["Destacar mensagens com texto piscante em chats", "Promover ofertas rápidas ou lembretes", "Saudar ou chamar atenção com uma frase curta", "Transformar seu texto pronto em figurinha para envio rápido"],
|
|
1330
|
+
"exemplos_reais": [
|
|
1331
|
+
{
|
|
1332
|
+
"situacao": "Promoção rápida com destaque.",
|
|
1333
|
+
"comando": "<prefix>figurinhatextopisca Promoção de 50% hoje!",
|
|
1334
|
+
"resposta_esperada": "Figura criada com sucesso.",
|
|
1335
|
+
"variacao": "<prefix>stb Promoção de 50% hoje!"
|
|
1336
|
+
},
|
|
1337
|
+
{
|
|
1338
|
+
"situacao": "Saudação breve.",
|
|
1339
|
+
"comando": "<prefix>figurinhatextopisca Olá, bom dia!",
|
|
1340
|
+
"resposta_esperada": "Figura criada com sucesso.",
|
|
1341
|
+
"variacao": "<prefix>stb Olá, bom dia!"
|
|
1342
|
+
},
|
|
1343
|
+
{
|
|
1344
|
+
"situacao": "Lembrete com até 4 linhas.",
|
|
1345
|
+
"comando": "<prefix>figurinhatextopisca Lembrete: entrega hoje Confira novidades",
|
|
1346
|
+
"resposta_esperada": "Figura criada com sucesso.",
|
|
1347
|
+
"variacao": "<prefix>stb Lembrete: entrega hoje Confira novidades."
|
|
1348
|
+
}
|
|
1349
|
+
],
|
|
1350
|
+
"resposta_esperada": ["Comando executado com sucesso.", "Formato de uso inválido. Consulte metodos_de_uso.", "Permissão insuficiente para executar este comando."],
|
|
1351
|
+
"erros_comuns_usuario": ["Texto excede 80 caracteres", "Mais de 4 linhas", "Não usar nenhum <prefix> no comando", "Texto vazio", "Texto com caracteres especiais não suportados"],
|
|
1352
|
+
"passos_se_der_erro": ["Verifique o tamanho do texto (≤ 80 caracteres) e o número de linhas (≤ 4).", "Tente novamente usando um dos comandos válidos com o mesmo texto.", "Confirme que você está logado via Google, conforme necessário.", "Se o erro continuar, tente novamente mais tarde ou procure suporte."],
|
|
1353
|
+
"resumo_usuario_origem": "auto_ia_assistida",
|
|
1354
|
+
"resumo_usuario_revisao_pendente": true
|
|
1210
1355
|
}
|
|
1211
1356
|
}
|
|
1212
1357
|
],
|
|
@@ -185,7 +185,7 @@ function checkMediaSize(mediaKey, mediaType, maxFileSize = MAX_FILE_SIZE) {
|
|
|
185
185
|
*/
|
|
186
186
|
function parseStickerMetaText(text, senderName) {
|
|
187
187
|
let packName = DEFAULT_STICKER_PACK_NAME;
|
|
188
|
-
let packAuthor = senderName || '
|
|
188
|
+
let packAuthor = senderName || 'Omnizap';
|
|
189
189
|
if (text) {
|
|
190
190
|
const idx = text.indexOf('/');
|
|
191
191
|
if (idx !== -1) {
|
|
@@ -7,7 +7,7 @@ Este arquivo e destinado a agentes de IA para gerar respostas no contexto dos co
|
|
|
7
7
|
- arquivo_base: `app/modules/stickerPackModule/commandConfig.json`
|
|
8
8
|
- schema_version: `2.0.0`
|
|
9
9
|
- module_enabled: `true`
|
|
10
|
-
- generated_at: `2026-03-
|
|
10
|
+
- generated_at: `2026-03-17T04:04:14.195Z`
|
|
11
11
|
|
|
12
12
|
## Escopo do Modulo
|
|
13
13
|
|
|
@@ -5,7 +5,11 @@ import { sanitizeText } from './stickerPackUtils.js';
|
|
|
5
5
|
* Serviço responsável por direcionar figurinhas recém-criadas para packs automáticos.
|
|
6
6
|
*/
|
|
7
7
|
const DEFAULT_AUTO_PACK_NAME = process.env.STICKER_PACK_AUTO_PACK_NAME || 'pack';
|
|
8
|
-
const
|
|
8
|
+
const VALID_VISIBILITIES = new Set(['public', 'unlisted', 'private']);
|
|
9
|
+
const AUTO_PACK_TARGET_VISIBILITY_RAW = String(process.env.STICKER_PACK_AUTO_COLLECT_VISIBILITY || process.env.STICKER_AUTO_PACK_BY_TAGS_VISIBILITY || 'public')
|
|
10
|
+
.trim()
|
|
11
|
+
.toLowerCase();
|
|
12
|
+
const AUTO_PACK_TARGET_VISIBILITY = VALID_VISIBILITIES.has(AUTO_PACK_TARGET_VISIBILITY_RAW) ? AUTO_PACK_TARGET_VISIBILITY_RAW : 'public';
|
|
9
13
|
const AUTO_COLLECT_ENABLED = process.env.STICKER_PACK_AUTO_COLLECT_ENABLED !== 'false';
|
|
10
14
|
const AUTO_PACK_NAME_MAX_LENGTH = 120;
|
|
11
15
|
const AUTO_PACK_DESCRIPTION_MARKER = '[auto-pack:collector]';
|
|
@@ -378,6 +378,35 @@
|
|
|
378
378
|
"schema": "legacy_v1_and_v2",
|
|
379
379
|
"legacy_name": "pacote",
|
|
380
380
|
"legacy_fields_present": ["descricao", "metodos_de_uso", "permissao_necessaria", "local_de_uso", "informacoes_coletadas", "argumentos", "pre_condicoes", "dependencias_externas", "efeitos_colaterais", "observabilidade", "privacidade", "acesso", "limite_uso_por_plano"]
|
|
381
|
+
},
|
|
382
|
+
"user_experience": {
|
|
383
|
+
"resumo_usuario": "Gerencie packs de figurinhas: criar, listar, adicionar figurinhas e enviar packs para contatos.",
|
|
384
|
+
"quando_usar": ["Criar um novo pack de figurinhas.", "Ver a lista de packs existentes.", "Adicionar figurinhas a um pack existente.", "Enviar um pack para alguém."],
|
|
385
|
+
"exemplos_reais": [
|
|
386
|
+
{
|
|
387
|
+
"situacao": "Criar um pack de figurinhas.",
|
|
388
|
+
"comando": "<prefix>pacote create meupack",
|
|
389
|
+
"resposta_esperada": "Pack criado com sucesso.",
|
|
390
|
+
"variacao": "Use nomes simples, sem aspas. Ex.: meupack."
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
"situacao": "Listar todos os packs.",
|
|
394
|
+
"comando": "<prefix>pacote list",
|
|
395
|
+
"resposta_esperada": "Listagem exibida com todos os packs.",
|
|
396
|
+
"variacao": "Pode retornar vários nomes; observe a lista completa."
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
"situacao": "Adicionar figurinhas a um pack existente.",
|
|
400
|
+
"comando": "<prefix>pacote add meupack",
|
|
401
|
+
"resposta_esperada": "Figurinhas adicionadas ao pack 'meupack'.",
|
|
402
|
+
"variacao": "Se houver figurinhas disponíveis, elas são incluídas."
|
|
403
|
+
}
|
|
404
|
+
],
|
|
405
|
+
"resposta_esperada": ["Comando executado com sucesso.", "Formato de uso inválido. Consulte metodos_de_uso.", "Permissão insuficiente para executar este comando."],
|
|
406
|
+
"erros_comuns_usuario": ["Esquecer de usar o prefixo correto no início do comando.", "Digitar o subcomando errado ou sem o parâmetro necessário.", "Tentar adicionar figurinhas sem indicar o pack ou sem estar logado.", "Tentar enviar sem ter criado ou sem selecionar um pack existente.", "Não estar logado com Google quando o comando exigir login."],
|
|
407
|
+
"passos_se_der_erro": ["Use <prefix>pacote help para confirmar a sintaxe correta.", "Verifique se o subcomando está entre create, list, add ou send e inclua os parâmetros necessários.", "Confirme que você está logado com Google, conforme exigido.", "Tente novamente após ajustar o comando. Se o erro persistir, copie a mensagem de erro e tente novamente mais tarde.", "Se não resolver, aguarde alguns minutos e procure ajuda com os detalhes do comando executado."],
|
|
408
|
+
"resumo_usuario_origem": "auto_ia_assistida",
|
|
409
|
+
"resumo_usuario_revisao_pendente": true
|
|
381
410
|
}
|
|
382
411
|
}
|
|
383
412
|
],
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { now as __timeNow, nowIso as __timeNowIso, toUnixMs as __timeNowMs } from '#time';
|
|
1
2
|
import { createHash } from 'node:crypto';
|
|
2
3
|
|
|
3
4
|
import OpenAI from 'openai';
|
|
@@ -177,7 +178,7 @@ const upsertSuggestionCacheRow = async ({ suggestionText, normalizedText, semant
|
|
|
177
178
|
};
|
|
178
179
|
|
|
179
180
|
const listSemanticClusters = async () => {
|
|
180
|
-
const now =
|
|
181
|
+
const now = __timeNowMs();
|
|
181
182
|
if (inMemoryClusterList.expiresAt > now && Array.isArray(inMemoryClusterList.items)) {
|
|
182
183
|
return inMemoryClusterList.items;
|
|
183
184
|
}
|
|
@@ -199,7 +200,7 @@ const listSemanticClusters = async () => {
|
|
|
199
200
|
}))
|
|
200
201
|
.filter((row) => row.id > 0 && Array.isArray(row.embedding) && row.embedding.length > 0);
|
|
201
202
|
inMemoryClusterList = {
|
|
202
|
-
expiresAt:
|
|
203
|
+
expiresAt: __timeNowMs() + RESOLUTION_CACHE_TTL_MS,
|
|
203
204
|
items: parsed,
|
|
204
205
|
};
|
|
205
206
|
for (const cluster of parsed) {
|
|
@@ -316,7 +317,7 @@ const resolveSemanticCluster = async (suggestionText) => {
|
|
|
316
317
|
if (!shouldRunSemanticClustering()) return null;
|
|
317
318
|
|
|
318
319
|
const memoryCached = inMemorySuggestionCache.get(normalizedSuggestion);
|
|
319
|
-
if (memoryCached && memoryCached.expiresAt >
|
|
320
|
+
if (memoryCached && memoryCached.expiresAt > __timeNowMs()) {
|
|
320
321
|
return memoryCached.value;
|
|
321
322
|
}
|
|
322
323
|
|
|
@@ -331,7 +332,7 @@ const resolveSemanticCluster = async (suggestionText) => {
|
|
|
331
332
|
suggestion: normalizedSuggestion,
|
|
332
333
|
};
|
|
333
334
|
inMemorySuggestionCache.set(normalizedSuggestion, {
|
|
334
|
-
expiresAt:
|
|
335
|
+
expiresAt: __timeNowMs() + RESOLUTION_CACHE_TTL_MS,
|
|
335
336
|
value: payload,
|
|
336
337
|
});
|
|
337
338
|
return payload;
|
|
@@ -360,7 +361,7 @@ const resolveSemanticCluster = async (suggestionText) => {
|
|
|
360
361
|
similarity: payload.similarity,
|
|
361
362
|
});
|
|
362
363
|
inMemorySuggestionCache.set(normalizedSuggestion, {
|
|
363
|
-
expiresAt:
|
|
364
|
+
expiresAt: __timeNowMs() + RESOLUTION_CACHE_TTL_MS,
|
|
364
365
|
value: payload,
|
|
365
366
|
});
|
|
366
367
|
return payload;
|
|
@@ -388,7 +389,7 @@ const resolveSemanticCluster = async (suggestionText) => {
|
|
|
388
389
|
similarity: 1,
|
|
389
390
|
});
|
|
390
391
|
inMemorySuggestionCache.set(normalizedSuggestion, {
|
|
391
|
-
expiresAt:
|
|
392
|
+
expiresAt: __timeNowMs() + RESOLUTION_CACHE_TTL_MS,
|
|
392
393
|
value: payload,
|
|
393
394
|
});
|
|
394
395
|
return payload;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { now as __timeNow, nowIso as __timeNowIso, toUnixMs as __timeNowMs } from '#time';
|
|
1
2
|
import logger from '#logger';
|
|
2
3
|
import { getActiveSocket } from '../../config/index.js';
|
|
3
4
|
import { normalizeJid, resolveBotJid } from '../../config/index.js';
|
|
@@ -165,7 +166,7 @@ const EFFECTIVE_COMPLETION_TRANSFER_ENABLED = COMPLETION_TRANSFER_ENABLED || IS_
|
|
|
165
166
|
const EFFECTIVE_MIGRATION_CANDIDATE_LIMIT = IS_AGGRESSIVE_PROFILE ? Math.max(MIGRATION_CANDIDATE_LIMIT, 24) : MIGRATION_CANDIDATE_LIMIT;
|
|
166
167
|
const EFFECTIVE_TRANSFER_CANDIDATE_SIMILARITY_FLOOR = IS_AGGRESSIVE_PROFILE ? Math.max(0.15, TRANSFER_CANDIDATE_SIMILARITY_FLOOR * 0.72) : TRANSFER_CANDIDATE_SIMILARITY_FLOOR;
|
|
167
168
|
|
|
168
|
-
const EXPLICIT_OWNER = String(process.env.STICKER_AUTO_PACK_OWNER_JID || process.env.USER_ADMIN || '').trim();
|
|
169
|
+
const EXPLICIT_OWNER = String(process.env.STICKER_AUTO_PACK_OWNER_JID || process.env.WHATSAPP_ADMIN_JID || process.env.USER_ADMIN || '').trim();
|
|
169
170
|
|
|
170
171
|
const LABEL_TO_TAG = {
|
|
171
172
|
'anime illustration': 'anime',
|
|
@@ -2888,7 +2889,7 @@ const updateAutoPackMetadata = async (packId, payload) => {
|
|
|
2888
2889
|
pack_theme_key: payload.themeKey,
|
|
2889
2890
|
pack_volume: payload.volume,
|
|
2890
2891
|
is_auto_pack: 1,
|
|
2891
|
-
last_rebalanced_at:
|
|
2892
|
+
last_rebalanced_at: __timeNow(),
|
|
2892
2893
|
};
|
|
2893
2894
|
if ('cover_sticker_id' in payload) {
|
|
2894
2895
|
fields.cover_sticker_id = payload.cover_sticker_id ?? null;
|
|
@@ -2908,7 +2909,7 @@ const createAutoPackVolume = async ({ ownerJid, theme, subtheme, themeKey, group
|
|
|
2908
2909
|
packThemeKey: themeKey,
|
|
2909
2910
|
packVolume: volume,
|
|
2910
2911
|
isAutoPack: true,
|
|
2911
|
-
lastRebalancedAt:
|
|
2912
|
+
lastRebalancedAt: __timeNow(),
|
|
2912
2913
|
});
|
|
2913
2914
|
};
|
|
2914
2915
|
|
|
@@ -3323,7 +3324,7 @@ export const runStickerAutoPackByTagsCycle = async ({ enableAdditions = true, en
|
|
|
3323
3324
|
}
|
|
3324
3325
|
|
|
3325
3326
|
running = true;
|
|
3326
|
-
const startedAt =
|
|
3327
|
+
const startedAt = __timeNowMs();
|
|
3327
3328
|
const budgets = { added: 0, removed: 0 };
|
|
3328
3329
|
let createdPacks = 0;
|
|
3329
3330
|
let processedGroups = 0;
|
|
@@ -3400,7 +3401,7 @@ export const runStickerAutoPackByTagsCycle = async ({ enableAdditions = true, en
|
|
|
3400
3401
|
pack_limit_skips: 0,
|
|
3401
3402
|
processed_groups: 0,
|
|
3402
3403
|
processed_volumes: 0,
|
|
3403
|
-
duration_ms:
|
|
3404
|
+
duration_ms: __timeNowMs() - startedAt,
|
|
3404
3405
|
});
|
|
3405
3406
|
logger.debug('Auto-pack por tags: nenhum grupo elegível neste ciclo.', {
|
|
3406
3407
|
action: 'sticker_auto_pack_by_tags_idle',
|
|
@@ -3451,7 +3452,7 @@ export const runStickerAutoPackByTagsCycle = async ({ enableAdditions = true, en
|
|
|
3451
3452
|
const fillRate = budgets.added / Math.max(1, processedVolumes * TARGET_PACK_SIZE);
|
|
3452
3453
|
|
|
3453
3454
|
recordStickerAutoPackCycle({
|
|
3454
|
-
durationMs:
|
|
3455
|
+
durationMs: __timeNowMs() - startedAt,
|
|
3455
3456
|
assetsScanned: Number(stats.assets_scanned || 0),
|
|
3456
3457
|
assetsAdded: budgets.added,
|
|
3457
3458
|
duplicateRate,
|
|
@@ -3468,7 +3469,7 @@ export const runStickerAutoPackByTagsCycle = async ({ enableAdditions = true, en
|
|
|
3468
3469
|
pack_limit_skips: Number(packLimitSkips || 0),
|
|
3469
3470
|
processed_groups: Number(processedGroups || 0),
|
|
3470
3471
|
processed_volumes: Number(processedVolumes || 0),
|
|
3471
|
-
duration_ms:
|
|
3472
|
+
duration_ms: __timeNowMs() - startedAt,
|
|
3472
3473
|
});
|
|
3473
3474
|
|
|
3474
3475
|
logger.info('Auto-pack por tags executado.', {
|
|
@@ -3492,7 +3493,7 @@ export const runStickerAutoPackByTagsCycle = async ({ enableAdditions = true, en
|
|
|
3492
3493
|
cohesion_rebuild_threshold: Number(COHESION_REBUILD_THRESHOLD.toFixed(6)),
|
|
3493
3494
|
duplicate_skips: duplicateSkips,
|
|
3494
3495
|
pack_limit_skips: packLimitSkips,
|
|
3495
|
-
duration_ms:
|
|
3496
|
+
duration_ms: __timeNowMs() - startedAt,
|
|
3496
3497
|
duplicate_rate: Number(duplicateRate.toFixed(6)),
|
|
3497
3498
|
rejection_rate: Number(rejectionRate.toFixed(6)),
|
|
3498
3499
|
pack_fill_rate: Number(fillRate.toFixed(6)),
|
|
@@ -3537,7 +3538,7 @@ export const runStickerAutoPackByTagsCycle = async ({ enableAdditions = true, en
|
|
|
3537
3538
|
pack_limit_skips: Number(packLimitSkips || 0),
|
|
3538
3539
|
processed_groups: Number(processedGroups || 0),
|
|
3539
3540
|
processed_volumes: Number(processedVolumes || 0),
|
|
3540
|
-
duration_ms:
|
|
3541
|
+
duration_ms: __timeNowMs() - startedAt,
|
|
3541
3542
|
});
|
|
3542
3543
|
} finally {
|
|
3543
3544
|
running = false;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { now as __timeNow, nowIso as __timeNowIso, toUnixMs as __timeNowMs } from '#time';
|
|
1
2
|
import fs from 'node:fs/promises';
|
|
2
3
|
import os from 'node:os';
|
|
3
4
|
|
|
@@ -299,14 +300,14 @@ const processDeterministicReclassification = async () => {
|
|
|
299
300
|
};
|
|
300
301
|
|
|
301
302
|
export const runStickerClassificationCycle = async ({ processPending = true, processReprocess = true, processDeterministic = true } = {}) => {
|
|
302
|
-
const startedAt =
|
|
303
|
+
const startedAt = __timeNowMs();
|
|
303
304
|
const shouldProcessClassifier = classifierConfig.enabled;
|
|
304
305
|
const shouldProcessDeterministic = deterministicReclassificationConfig.enabled;
|
|
305
306
|
|
|
306
307
|
if (!BACKGROUND_ENABLED || (!shouldProcessClassifier && !shouldProcessDeterministic)) {
|
|
307
308
|
recordStickerClassificationCycle({
|
|
308
309
|
status: 'skipped',
|
|
309
|
-
durationMs:
|
|
310
|
+
durationMs: __timeNowMs() - startedAt,
|
|
310
311
|
processed: 0,
|
|
311
312
|
classified: 0,
|
|
312
313
|
failed: 0,
|
|
@@ -325,7 +326,7 @@ export const runStickerClassificationCycle = async ({ processPending = true, pro
|
|
|
325
326
|
const processed = Number(pendingStats?.processed || 0) + Number(reprocessStats?.processed || 0) + Number(deterministicStats?.processed || 0);
|
|
326
327
|
const classified = Number(pendingStats?.classified || 0) + Number(reprocessStats?.classified || 0) + Number(deterministicStats?.updated || 0);
|
|
327
328
|
const failed = Number(pendingStats?.failed || 0) + Number(reprocessStats?.failed || 0) + Number(deterministicStats?.failed || 0);
|
|
328
|
-
const durationMs =
|
|
329
|
+
const durationMs = __timeNowMs() - startedAt;
|
|
329
330
|
|
|
330
331
|
recordStickerClassificationCycle({
|
|
331
332
|
status: 'ok',
|
|
@@ -345,7 +346,7 @@ export const runStickerClassificationCycle = async ({ processPending = true, pro
|
|
|
345
346
|
} catch (error) {
|
|
346
347
|
recordStickerClassificationCycle({
|
|
347
348
|
status: 'failed',
|
|
348
|
-
durationMs:
|
|
349
|
+
durationMs: __timeNowMs() - startedAt,
|
|
349
350
|
processed: 0,
|
|
350
351
|
classified: 0,
|
|
351
352
|
failed: 1,
|
|
@@ -407,7 +408,7 @@ const classifyBatch = async () => {
|
|
|
407
408
|
}
|
|
408
409
|
|
|
409
410
|
running = true;
|
|
410
|
-
const startedAt =
|
|
411
|
+
const startedAt = __timeNowMs();
|
|
411
412
|
|
|
412
413
|
try {
|
|
413
414
|
const result = await runStickerClassificationCycle({
|
|
@@ -459,7 +460,7 @@ const classifyBatch = async () => {
|
|
|
459
460
|
deterministic_reclassification_failed: Number(deterministic.failed || 0),
|
|
460
461
|
deterministic_reclassification_batches: Number(deterministic.batches || 0),
|
|
461
462
|
deterministic_reclassification_last_cursor: deterministic.last_cursor || null,
|
|
462
|
-
duration_ms:
|
|
463
|
+
duration_ms: __timeNowMs() - startedAt,
|
|
463
464
|
batch_size: BATCH_SIZE,
|
|
464
465
|
concurrency: BACKGROUND_CONCURRENCY,
|
|
465
466
|
gain_count: gainCount,
|
|
@@ -472,7 +473,7 @@ const classifyBatch = async () => {
|
|
|
472
473
|
processed: Number(processed || 0),
|
|
473
474
|
classified: Number(classified || 0),
|
|
474
475
|
failed: Number(failed || 0),
|
|
475
|
-
duration_ms:
|
|
476
|
+
duration_ms: __timeNowMs() - startedAt,
|
|
476
477
|
};
|
|
477
478
|
} catch (error) {
|
|
478
479
|
logger.error('Falha no loop de classificação em background.', {
|
|
@@ -483,7 +484,7 @@ const classifyBatch = async () => {
|
|
|
483
484
|
executed: true,
|
|
484
485
|
reason: 'failed',
|
|
485
486
|
gain_count: 0,
|
|
486
|
-
duration_ms:
|
|
487
|
+
duration_ms: __timeNowMs() - startedAt,
|
|
487
488
|
};
|
|
488
489
|
} finally {
|
|
489
490
|
running = false;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { now as __timeNow, nowIso as __timeNowIso, toUnixMs as __timeNowMs } from '#time';
|
|
1
2
|
import logger from '#logger';
|
|
2
3
|
import { setQueueDepth } from '../../observability/metrics.js';
|
|
3
4
|
import { isFeatureEnabled } from '../../services/infra/featureFlagService.js';
|
|
@@ -51,9 +52,9 @@ const enqueueTaskSafely = async ({ taskType, payload, priority, idempotencyKey }
|
|
|
51
52
|
};
|
|
52
53
|
|
|
53
54
|
const toUnixSeconds = (value) => {
|
|
54
|
-
if (!value) return Math.floor(
|
|
55
|
+
if (!value) return Math.floor(__timeNowMs() / 1000);
|
|
55
56
|
const numeric = Date.parse(value);
|
|
56
|
-
if (!Number.isFinite(numeric)) return Math.floor(
|
|
57
|
+
if (!Number.isFinite(numeric)) return Math.floor(__timeNowMs() / 1000);
|
|
57
58
|
return Math.floor(numeric / 1000);
|
|
58
59
|
};
|
|
59
60
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { now as __timeNow, nowIso as __timeNowIso, toUnixMs as __timeNowMs } from '#time';
|
|
1
2
|
import { listClassificationCategoryDistribution } from './stickerAssetClassificationRepository.js';
|
|
2
3
|
|
|
3
4
|
const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
|
@@ -75,7 +76,7 @@ const buildDynamicWeights = (driftScore) => {
|
|
|
75
76
|
export const getBaseMarketplaceWeights = () => BASE_WEIGHTS;
|
|
76
77
|
|
|
77
78
|
export const getMarketplaceDriftSnapshot = async ({ force = false } = {}) => {
|
|
78
|
-
const now =
|
|
79
|
+
const now = __timeNowMs();
|
|
79
80
|
if (!force && now < cache.expiresAt) {
|
|
80
81
|
return cache;
|
|
81
82
|
}
|