mega-brain-ai 1.1.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.
Potentially problematic release.
This version of mega-brain-ai might be problematic. Click here for more details.
- package/.claude/CLAUDE.md +155 -0
- package/.claude/commands/agents.md +161 -0
- package/.claude/commands/ask.md +117 -0
- package/.claude/commands/benchmark.md +224 -0
- package/.claude/commands/chat.md +343 -0
- package/.claude/commands/compare.md +116 -0
- package/.claude/commands/conclave.md +194 -0
- package/.claude/commands/config.md +133 -0
- package/.claude/commands/council.md +194 -0
- package/.claude/commands/create-agent.md +452 -0
- package/.claude/commands/debate.md +157 -0
- package/.claude/commands/documentation/create-architecture-documentation.md +175 -0
- package/.claude/commands/dossiers.md +180 -0
- package/.claude/commands/evolve.md +223 -0
- package/.claude/commands/extract-dna.md +170 -0
- package/.claude/commands/extract-knowledge.md +507 -0
- package/.claude/commands/inbox.md +296 -0
- package/.claude/commands/ingest-empresa.md +191 -0
- package/.claude/commands/ingest.md +182 -0
- package/.claude/commands/jarvis-briefing.md +67 -0
- package/.claude/commands/jarvis-control.md +169 -0
- package/.claude/commands/jarvis-full.md +181 -0
- package/.claude/commands/jarvis.md +212 -0
- package/.claude/commands/ler-drive.md +212 -0
- package/.claude/commands/log.md +158 -0
- package/.claude/commands/loop.md +133 -0
- package/.claude/commands/loops.md +73 -0
- package/.claude/commands/mission-autopilot.md +538 -0
- package/.claude/commands/mission.md +353 -0
- package/.claude/commands/process-inbox.md +148 -0
- package/.claude/commands/process-jarvis.md +3036 -0
- package/.claude/commands/process-video.md +131 -0
- package/.claude/commands/rag-search.md +78 -0
- package/.claude/commands/resume.md +33 -0
- package/.claude/commands/save.md +38 -0
- package/.claude/commands/scan-inbox.md +125 -0
- package/.claude/commands/setup.md +99 -0
- package/.claude/commands/system-digest.md +243 -0
- package/.claude/commands/verify.md +182 -0
- package/.claude/commands/view-dna.md +169 -0
- package/.claude/hooks/agent_doctor.py +433 -0
- package/.claude/hooks/agent_memory_persister.py +203 -0
- package/.claude/hooks/auto_formatter.py +158 -0
- package/.claude/hooks/checkpoint_writer.py +244 -0
- package/.claude/hooks/claude_md_guard.py +146 -0
- package/.claude/hooks/creation_validator.py +357 -0
- package/.claude/hooks/enforce_dual_location.py +501 -0
- package/.claude/hooks/enforce_plan_mode.py +220 -0
- package/.claude/hooks/inbox_age_alert.py +367 -0
- package/.claude/hooks/jarvis_briefing.py +506 -0
- package/.claude/hooks/ledger_updater.py +301 -0
- package/.claude/hooks/memory_hints_injector.py +251 -0
- package/.claude/hooks/memory_updater.py +202 -0
- package/.claude/hooks/multi_agent_hook.py +464 -0
- package/.claude/hooks/notification_system.py +120 -0
- package/.claude/hooks/pattern_analyzer.py +526 -0
- package/.claude/hooks/pending_tracker.py +188 -0
- package/.claude/hooks/post_batch_cascading.py +1740 -0
- package/.claude/hooks/post_output_validator.py +358 -0
- package/.claude/hooks/post_tool_use.py +120 -0
- package/.claude/hooks/post_write_validator.py +200 -0
- package/.claude/hooks/quality_watchdog.py +394 -0
- package/.claude/hooks/ralph_wiggum.py +277 -0
- package/.claude/hooks/session-source-sync.py +218 -0
- package/.claude/hooks/session_autosave_v2.py +1135 -0
- package/.claude/hooks/session_end.py +203 -0
- package/.claude/hooks/session_start.py +939 -0
- package/.claude/hooks/skill_indexer.py +48 -0
- package/.claude/hooks/skill_router.py +358 -0
- package/.claude/hooks/stop_hook_completeness.py +178 -0
- package/.claude/hooks/subagent_tracker.py +163 -0
- package/.claude/hooks/token_checkpoint.py +584 -0
- package/.claude/hooks/user_prompt_submit.py +125 -0
- package/.claude/rules/ANTHROPIC-STANDARDS.md +384 -0
- package/.claude/rules/CLAUDE-LITE.md +201 -0
- package/.claude/rules/RULE-GROUP-1.md +320 -0
- package/.claude/rules/RULE-GROUP-2.md +307 -0
- package/.claude/rules/RULE-GROUP-3.md +248 -0
- package/.claude/rules/RULE-GROUP-4.md +427 -0
- package/.claude/rules/RULE-GROUP-5.md +388 -0
- package/.claude/rules/RULE-GROUP-6.md +387 -0
- package/.claude/rules/logging.md +53 -0
- package/.claude/rules/mcp-governance.md +128 -0
- package/.claude/rules/pipeline.md +60 -0
- package/.claude/rules/state-management.md +93 -0
- package/.claude/scripts/apply-tags.py +77 -0
- package/.claude/scripts/batch-extract-transcriptions.py +132 -0
- package/.claude/scripts/build-complete-index.py +250 -0
- package/.claude/scripts/build-planilha-index.py +170 -0
- package/.claude/scripts/complete-tag-matching.py +250 -0
- package/.claude/scripts/deduplicate-inbox.py +139 -0
- package/.claude/scripts/docx-xml-extractor.py +141 -0
- package/.claude/scripts/extract-docx-text.py +58 -0
- package/.claude/scripts/extract-single-transcription.py +74 -0
- package/.claude/scripts/extract_docx_from_gdrive.py +77 -0
- package/.claude/scripts/organized-downloader.py +246 -0
- package/.claude/scripts/planilha-tagger.py +187 -0
- package/.claude/scripts/revert-tags.py +70 -0
- package/.claude/scripts/source-sync.py +265 -0
- package/.claude/scripts/tag-inbox-files.py +276 -0
- package/.claude/scripts/tag-inbox-v2.py +253 -0
- package/.claude/scripts/test-extraction.py +35 -0
- package/.claude/scripts/test-full-extraction.py +74 -0
- package/.claude/skills/00-SKILL-CREATOR/SKILL.md +186 -0
- package/.claude/skills/01-SKILL-DOCS-MEGABRAIN/SKILL.md +251 -0
- package/.claude/skills/02-SKILL-PYTHON-MEGABRAIN/SKILL.md +323 -0
- package/.claude/skills/03-SKILL-AGENT-CREATION/SKILL.md +374 -0
- package/.claude/skills/04-SKILL-KNOWLEDGE-EXTRACTION/SKILL.md +318 -0
- package/.claude/skills/05-SKILL-PIPELINE-JARVIS/SKILL.md +430 -0
- package/.claude/skills/06-SKILL-BRAINSTORMING/SKILL.md +72 -0
- package/.claude/skills/07-SKILL-DISPATCHING-PARALLEL-AGENTS/SKILL.md +193 -0
- package/.claude/skills/08-SKILL-EXECUTING-PLANS/SKILL.md +114 -0
- package/.claude/skills/09-SKILL-WRITING-PLANS/SKILL.md +184 -0
- package/.claude/skills/10-SKILL-VERIFICATION-BEFORE-COMPLETION/SKILL.md +130 -0
- package/.claude/skills/11-SKILL-USING-SUPERPOWERS/SKILL.md +105 -0
- package/.claude/skills/DETECTION-PROTOCOL.md +217 -0
- package/.claude/skills/README.md +240 -0
- package/.claude/skills/SKILL-REGISTRY.md +284 -0
- package/.claude/skills/SKILL-SUGGESTIONS.md +114 -0
- package/.claude/skills/_TEMPLATES/SKILL-WRITER-GUIDE.md +385 -0
- package/.claude/skills/chronicler/SKILL.md +146 -0
- package/.claude/skills/chronicler/chronicler_core.py +468 -0
- package/.claude/skills/code-review/SKILL.md +160 -0
- package/.claude/skills/council/SKILL.md +210 -0
- package/.claude/skills/executor/SKILL.md +161 -0
- package/.claude/skills/fase-2-5-tagging/SKILL.md +182 -0
- package/.claude/skills/feature-dev/SKILL.md +154 -0
- package/.claude/skills/finance-agent/SKILL.md +137 -0
- package/.claude/skills/frontend-design/SKILL.md +165 -0
- package/.claude/skills/gdrive-transcription-downloader/SKILL.md +249 -0
- package/.claude/skills/gemini-fallback/SKILL.md +67 -0
- package/.claude/skills/gemini-fallback/gemini_fetch.py +0 -0
- package/.claude/skills/gha/SKILL.md +96 -0
- package/.claude/skills/gha/gha_diagnostic.py +227 -0
- package/.claude/skills/github-workflow/SKILL.md +190 -0
- package/.claude/skills/hookify/SKILL.md +134 -0
- package/.claude/skills/hybrid-source-reading/SKILL.md +265 -0
- package/.claude/skills/jarvis/SKILL.md +546 -0
- package/.claude/skills/jarvis-briefing/SKILL.md +340 -0
- package/.claude/skills/ler-planilha/SKILL.md +281 -0
- package/.claude/skills/plugin-dev/SKILL.md +176 -0
- package/.claude/skills/pr-review-toolkit/SKILL.md +178 -0
- package/.claude/skills/resume/SKILL.md +61 -0
- package/.claude/skills/save/SKILL.md +87 -0
- package/.claude/skills/skill-writer/SKILL.md +153 -0
- package/.claude/skills/skill-writer/examples.md +191 -0
- package/.claude/skills/skill-writer/troubleshooting.md +205 -0
- package/.claude/skills/smart-download-tagger/SKILL.md +148 -0
- package/.claude/skills/source-sync/SKILL.md +240 -0
- package/.claude/skills/sync-docs/SKILL.md +193 -0
- package/.claude/skills/sync-docs/config.json +37 -0
- package/.claude/skills/sync-docs/gdrive_sync.py +358 -0
- package/.claude/skills/sync-docs/reauth.py +71 -0
- package/.claude/skills/talent-agent/SKILL.md +183 -0
- package/.claude/skills/verify/SKILL.md +154 -0
- package/.claude/skills/verify/verify_runner.py +0 -0
- package/.claude/skills/verify-6-levels/SKILL.md +234 -0
- package/.claude/templates/BATCH-LOG-TEMPLATE.md +221 -0
- package/.claudeignore +9 -0
- package/.gitattributes +4 -0
- package/.github/layer1-allowlist.txt +80 -0
- package/.github/layer2-manifest.txt +40 -0
- package/.gitignore +219 -0
- package/README.md +1210 -0
- package/agents/_templates/INDEX.md +741 -0
- package/agents/_templates/TEMPLATE-AGENT-MD-ULTRA-ROBUSTO-V3.md +2399 -0
- package/agents/boardroom/CHECKLIST-MASTER.md +281 -0
- package/agents/boardroom/INTEGRATION-GUIDE.md +406 -0
- package/agents/boardroom/README.md +238 -0
- package/agents/boardroom/config/BOARDROOM-CONFIG.md +186 -0
- package/agents/boardroom/config/TTS-INTEGRATION.md +258 -0
- package/agents/boardroom/config/VOICE-PROFILES.md +624 -0
- package/agents/boardroom/config/voice_mapping.json +128 -0
- package/agents/boardroom/scripts/audio_generator.py +375 -0
- package/agents/boardroom/scripts/audio_generator_edge.py +353 -0
- package/agents/boardroom/scripts/jarvis_boardroom_hook.py +415 -0
- package/agents/boardroom/scripts/notebooklm_generator.py +578 -0
- package/agents/boardroom/templates/EPISODE-TEMPLATE.md +367 -0
- package/agents/boardroom/templates/scene-templates/SCENE-AGENT-DEBATE.md +252 -0
- package/agents/boardroom/templates/scene-templates/SCENE-COUNCIL.md +270 -0
- package/agents/boardroom/templates/scene-templates/SCENE-DNA-CONSULTATION.md +126 -0
- package/agents/boardroom/templates/scene-templates/SCENE-QUESTION.md +174 -0
- package/agents/boardroom/workflows/WORKFLOW-AUDIO-GENERATION.md +421 -0
- package/agents/constitution/BASE-CONSTITUTION.md +254 -0
- package/agents/council/CRITIC.md +197 -0
- package/agents/council/DEVILS-ADVOCATE.md +274 -0
- package/agents/council/SYNTHESIZER.md +293 -0
- package/agents/council/advogado-do-diabo/AGENT.md +489 -0
- package/agents/council/advogado-do-diabo/SOUL.md +100 -0
- package/agents/council/critico-metodologico/AGENT.md +670 -0
- package/agents/council/critico-metodologico/SOUL.md +107 -0
- package/agents/council/sintetizador/AGENT.md +558 -0
- package/agents/council/sintetizador/SOUL.md +94 -0
- package/agents/persons/_example/AGENT-EXAMPLE.md +42 -0
- package/agents/persons/_example/DNA-EXAMPLE.yaml +61 -0
- package/agents/protocols/AGENT-COGNITION-PROTOCOL.md +779 -0
- package/agents/protocols/AGENT-INTEGRITY-PROTOCOL.md +692 -0
- package/agents/protocols/BATCH-VISUAL-PROTOCOL.md +841 -0
- package/agents/protocols/DNA-CONFIG-TEMPLATE.yaml +181 -0
- package/agents/protocols/DNA-EXTRACTION-PROTOCOL.md +370 -0
- package/agents/protocols/EPISTEMIC-PROTOCOL.md +333 -0
- package/agents/protocols/LOG-STRUCTURE-PROTOCOL.md +65 -0
- package/agents/protocols/MEMORY-PROTOCOL.md +567 -0
- package/agents/protocols/NARRATIVE-SYNTHESIS-PROTOCOL.md +278 -0
- package/agents/protocols/PHASE-4-VERIFICATION-CHECKPOINT.md +146 -0
- package/agents/protocols/SOUL-TEMPLATE.md +416 -0
- package/agents/protocols/TEMPLATE-EVOLUTION-PROTOCOL.md +544 -0
- package/agents/protocols/VISUAL-DIFF-PROTOCOL.md +159 -0
- package/agents/sua-empresa/README.md +44 -0
- package/agents/sua-empresa/_example/jds/EXAMPLE-JD.md +42 -0
- package/agents/sua-empresa/_example/org/EXAMPLE-ORG.md +32 -0
- package/agents/sua-empresa/_example/roles/EXAMPLE-ROLE.md +38 -0
- package/bin/cli.js +2 -0
- package/bin/lib/ascii-art.js +234 -0
- package/bin/lib/installer.js +402 -0
- package/bin/lib/setup-wizard.js +95 -0
- package/bin/lib/validate-email.js +109 -0
- package/bin/mega-brain.js +97 -0
- package/bin/push.js +342 -0
- package/bin/templates/env.example +38 -0
- package/inbox/.gitkeep +0 -0
- package/integrations/README.md +46 -0
- package/integrations/mcps/MCP-REGISTRY.md +56 -0
- package/integrations/mcps/excalidraw/CONFIG.md +56 -0
- package/integrations/mcps/gdrive/CONFIG.md +38 -0
- package/knowledge/dna/.gitkeep +0 -0
- package/knowledge/dossiers/persons/.gitkeep +0 -0
- package/knowledge/dossiers/persons/DOSSIER-EXAMPLE.md +49 -0
- package/knowledge/dossiers/system/.gitkeep +0 -0
- package/knowledge/dossiers/themes/.gitkeep +0 -0
- package/knowledge/playbooks/.gitkeep +0 -0
- package/knowledge/playbooks/PLAYBOOK-EXAMPLE.md +50 -0
- package/knowledge/sources/.gitkeep +0 -0
- package/logs/.gitkeep +0 -0
- package/package.json +128 -0
- package/processing/canonical/.gitkeep +0 -0
- package/processing/chunks/.gitkeep +0 -0
- package/processing/insights/.gitkeep +0 -0
- package/processing/narratives/.gitkeep +0 -0
- package/reference/CONSELHO.md +337 -0
- package/reference/CONTEXT7_README.md +28 -0
- package/reference/JARVIS-LOGGING-PROTOCOL.md +380 -0
- package/reference/QUICK-START.md +197 -0
- package/reference/README-RALPH-CASCATEAMENTO.md +207 -0
- package/reference/TEMPLATE-MASTER.md +727 -0
- package/reference/prds/prd-jarvis-mega-brain-v3.md +1305 -0
- package/reference/templates/phase5/IMPLEMENTATION-GUIDE.md +355 -0
- package/reference/templates/phase5/MOGA-BRAIN-PHASE5-TEMPLATES.md +1284 -0
- package/reference/templates/phase5/README.md +165 -0
- package/reference/workflow-claude-code-boris-cherny-continuous-claude.md +2232 -0
- package/system/database/001_moneyclub_buyers.sql +160 -0
- package/system/database/002_premium_token.sql +97 -0
- package/system/database/apply-migration.mjs +129 -0
- package/system/docs/MEGA-BRAIN-DEMO-COMPLETA.md +1226 -0
- package/system/docs/MEGA-BRAIN-MANIFESTO-COMPLETO.md +1054 -0
- package/system/docs/MOGA-BRAIN-EXPLICACAO-COMPLETA.md +791 -0
- package/system/docs/STRATEGIC-INTEGRATION-GUIDE.md +725 -0
- package/system/docs/architecture/01-system-context.md +136 -0
- package/system/docs/architecture/02-components.md +225 -0
- package/system/docs/architecture/03-data-flow.md +235 -0
- package/system/docs/architecture/04-integrations.md +283 -0
- package/system/docs/architecture/README.md +71 -0
- package/system/docs/architecture/diagrams/component-diagram.mmd +50 -0
- package/system/docs/architecture/diagrams/data-flow.mmd +39 -0
- package/system/docs/architecture/diagrams/system-overview.mmd +68 -0
- package/system/protocols/AGENT-AUTHORITY.md +217 -0
- package/system/protocols/CONSTITUICAO-BASE.md +115 -0
- package/system/protocols/CONSTITUTION.md +231 -0
- package/system/protocols/GOVERNANCE-MAP.md +123 -0
- package/system/protocols/HOOK-SECURITY-THREAT-MODEL.md +152 -0
- package/system/protocols/ORQUESTRACAO-PROTOCOL.md +215 -0
- package/system/protocols/_archive/CHUNKING-PROTOCOL.md +207 -0
- package/system/protocols/_archive/ENTITY-RESOLUTION-PROTOCOL.md +269 -0
- package/system/protocols/_archive/INSIGHT-EXTRACTION-PROTOCOL.md +257 -0
- package/system/protocols/_archive/NARRATIVE-SYNTHESIS-PROTOCOL.md +290 -0
- package/system/protocols/agents/AGENT-INTERACTION.md +315 -0
- package/system/protocols/agents/CORTEX-PROTOCOL.md +520 -0
- package/system/protocols/agents/EPISTEMIC-PROTOCOL.md +465 -0
- package/system/protocols/agents/MEMORY-PROTOCOL.md +366 -0
- package/system/protocols/agents/WAR-ROOM.md +355 -0
- package/system/protocols/company/COMPANY-DOCUMENT-PROTOCOL.md +793 -0
- package/system/protocols/company/COMPANY-ENRICHMENT-PROTOCOL.md +679 -0
- package/system/protocols/conclave/CONCLAVE-LOG-TEMPLATE-v2.md +309 -0
- package/system/protocols/conclave/CONCLAVE-PROTOCOL.md +518 -0
- package/system/protocols/conclave/DEBATE-DYNAMICS-CONFIG.yaml +322 -0
- package/system/protocols/conclave/DEBATE-DYNAMICS-PROTOCOL.md +613 -0
- package/system/protocols/conclave/DEBATE-PROTOCOL.md +323 -0
- package/system/protocols/council/COUNCIL-LOG-TEMPLATE-v2.md +309 -0
- package/system/protocols/council/COUNCIL-PROTOCOL.md +518 -0
- package/system/protocols/council/DEBATE-DYNAMICS-CONFIG.yaml +322 -0
- package/system/protocols/council/DEBATE-DYNAMICS-PROTOCOL.md +613 -0
- package/system/protocols/council/DEBATE-PROTOCOL.md +323 -0
- package/system/protocols/dna/DNA-EXTRACTION-PROTOCOL.md +1214 -0
- package/system/protocols/dna/ENRICHMENT-PROTOCOL.md +408 -0
- package/system/protocols/dna/REASONING-MODEL-PROTOCOL.md +331 -0
- package/system/protocols/pipeline/DOSSIER-COMPILATION-PROTOCOL.md +790 -0
- package/system/protocols/pipeline/NARRATIVE-METABOLISM-PROTOCOL.md +292 -0
- package/system/protocols/pipeline/PIPELINE-JARVIS-v2.1.md +606 -0
- package/system/protocols/pipeline/PROMPT-1.1-CHUNKING.md +154 -0
- package/system/protocols/pipeline/PROMPT-1.2-ENTITY-RESOLUTION.md +186 -0
- package/system/protocols/pipeline/PROMPT-2.1-DNA-TAGS-INCREMENT.md +208 -0
- package/system/protocols/pipeline/PROMPT-2.1-INSIGHT-EXTRACTION.md +191 -0
- package/system/protocols/pipeline/PROMPT-3.1-NARRATIVE-SYNTHESIS.md +331 -0
- package/system/protocols/pipeline/SOURCES-COMPILATION-PROTOCOL.md +340 -0
- package/system/protocols/system/AUTO-LOG-PROTOCOL.md +369 -0
- package/system/protocols/system/CHECKPOINT-ENFORCEMENT.md +176 -0
- package/system/protocols/system/ENFORCEMENT.md +435 -0
- package/system/protocols/system/LOG-TEMPLATES.md +1068 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
NOTIFICATION SYSTEM
|
|
4
|
+
===================
|
|
5
|
+
Envia notificações do sistema quando Claude precisa de input ou completa tarefas.
|
|
6
|
+
|
|
7
|
+
Baseado no workflow Boris Cherny: "I use system notifications to know when a Claude needs input"
|
|
8
|
+
|
|
9
|
+
Platforms:
|
|
10
|
+
- macOS: osascript (native notifications)
|
|
11
|
+
- Terminal: bell + print
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
python3 notification_system.py "Title" "Message" [type]
|
|
15
|
+
|
|
16
|
+
Types:
|
|
17
|
+
- info: Informational (default)
|
|
18
|
+
- success: Task completed
|
|
19
|
+
- warning: Needs attention
|
|
20
|
+
- error: Something failed
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import sys
|
|
24
|
+
import os
|
|
25
|
+
import subprocess
|
|
26
|
+
from datetime import datetime
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
|
|
29
|
+
PROJECT_ROOT = Path(os.environ.get('CLAUDE_PROJECT_DIR', '.'))
|
|
30
|
+
LOGS_PATH = PROJECT_ROOT / 'logs' / 'notifications'
|
|
31
|
+
LOGS_PATH.mkdir(parents=True, exist_ok=True)
|
|
32
|
+
|
|
33
|
+
def send_macos_notification(title: str, message: str, sound: str = "default"):
|
|
34
|
+
"""Send native macOS notification"""
|
|
35
|
+
script = f'''
|
|
36
|
+
display notification "{message}" with title "{title}" sound name "{sound}"
|
|
37
|
+
'''
|
|
38
|
+
try:
|
|
39
|
+
subprocess.run(['osascript', '-e', script], capture_output=True, timeout=5)
|
|
40
|
+
return True
|
|
41
|
+
except Exception:
|
|
42
|
+
return False
|
|
43
|
+
|
|
44
|
+
def send_terminal_bell():
|
|
45
|
+
"""Send terminal bell character"""
|
|
46
|
+
print('\a', end='', flush=True)
|
|
47
|
+
|
|
48
|
+
def log_notification(title: str, message: str, notif_type: str):
|
|
49
|
+
"""Log notification"""
|
|
50
|
+
log_file = LOGS_PATH / 'notifications.jsonl'
|
|
51
|
+
import json
|
|
52
|
+
entry = {
|
|
53
|
+
'timestamp': datetime.now().isoformat(),
|
|
54
|
+
'title': title,
|
|
55
|
+
'message': message,
|
|
56
|
+
'type': notif_type
|
|
57
|
+
}
|
|
58
|
+
with open(log_file, 'a') as f:
|
|
59
|
+
f.write(json.dumps(entry) + '\n')
|
|
60
|
+
|
|
61
|
+
def get_sound_for_type(notif_type: str) -> str:
|
|
62
|
+
"""Get appropriate sound for notification type"""
|
|
63
|
+
sounds = {
|
|
64
|
+
'info': 'Pop',
|
|
65
|
+
'success': 'Glass',
|
|
66
|
+
'warning': 'Basso',
|
|
67
|
+
'error': 'Sosumi'
|
|
68
|
+
}
|
|
69
|
+
return sounds.get(notif_type, 'default')
|
|
70
|
+
|
|
71
|
+
def main():
|
|
72
|
+
if len(sys.argv) < 3:
|
|
73
|
+
print("Usage: notification_system.py 'Title' 'Message' [type]")
|
|
74
|
+
sys.exit(1)
|
|
75
|
+
|
|
76
|
+
title = sys.argv[1]
|
|
77
|
+
message = sys.argv[2]
|
|
78
|
+
notif_type = sys.argv[3] if len(sys.argv) > 3 else 'info'
|
|
79
|
+
|
|
80
|
+
# Log
|
|
81
|
+
log_notification(title, message, notif_type)
|
|
82
|
+
|
|
83
|
+
# Send macOS notification
|
|
84
|
+
sound = get_sound_for_type(notif_type)
|
|
85
|
+
macos_success = send_macos_notification(title, message, sound)
|
|
86
|
+
|
|
87
|
+
# Also send terminal bell
|
|
88
|
+
send_terminal_bell()
|
|
89
|
+
|
|
90
|
+
# Print to terminal as fallback
|
|
91
|
+
icons = {
|
|
92
|
+
'info': 'ℹ️',
|
|
93
|
+
'success': '✅',
|
|
94
|
+
'warning': '⚠️',
|
|
95
|
+
'error': '❌'
|
|
96
|
+
}
|
|
97
|
+
icon = icons.get(notif_type, 'ℹ️')
|
|
98
|
+
print(f"\n{icon} [{title}] {message}\n")
|
|
99
|
+
|
|
100
|
+
sys.exit(0)
|
|
101
|
+
|
|
102
|
+
# Convenience functions for direct import
|
|
103
|
+
def notify_needs_input(context: str = ""):
|
|
104
|
+
"""Notify that Claude needs user input"""
|
|
105
|
+
msg = f"Claude needs your input{': ' + context if context else ''}"
|
|
106
|
+
send_macos_notification("🤖 JARVIS", msg, "Basso")
|
|
107
|
+
send_terminal_bell()
|
|
108
|
+
|
|
109
|
+
def notify_task_complete(task: str = ""):
|
|
110
|
+
"""Notify that a task completed"""
|
|
111
|
+
msg = f"Task completed{': ' + task if task else ''}"
|
|
112
|
+
send_macos_notification("✅ JARVIS", msg, "Glass")
|
|
113
|
+
|
|
114
|
+
def notify_error(error: str = ""):
|
|
115
|
+
"""Notify about an error"""
|
|
116
|
+
msg = f"Error{': ' + error if error else ''}"
|
|
117
|
+
send_macos_notification("❌ JARVIS", msg, "Sosumi")
|
|
118
|
+
|
|
119
|
+
if __name__ == '__main__':
|
|
120
|
+
main()
|
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Pattern Analyzer - Layer 3 do META-AGENT System v1.0
|
|
4
|
+
|
|
5
|
+
FUNÇÃO: Detecta padrões de request e aprende preferências do usuário.
|
|
6
|
+
Sugere criação de skills quando padrões recorrentes são detectados.
|
|
7
|
+
|
|
8
|
+
REGRA #28: META-AGENT QUALITY AWARENESS
|
|
9
|
+
PRINCÍPIO: Aprende INDIRETAMENTE, não pergunta
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import os
|
|
14
|
+
import re
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from datetime import datetime
|
|
17
|
+
from collections import defaultdict
|
|
18
|
+
from typing import Dict, List, Optional
|
|
19
|
+
|
|
20
|
+
PROJECT_ROOT = Path(os.environ.get('CLAUDE_PROJECT_DIR', '.'))
|
|
21
|
+
LOGS_PATH = PROJECT_ROOT / "logs"
|
|
22
|
+
PATTERNS_LOG = LOGS_PATH / "learning_patterns.jsonl"
|
|
23
|
+
PREFERENCES_LOG = LOGS_PATH / "preferences.jsonl"
|
|
24
|
+
SKILL_SUGGESTIONS_LOG = LOGS_PATH / "skill_suggestions.jsonl"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
28
|
+
# FEEDBACK SIGNALS (APRENDIZADO INDIRETO)
|
|
29
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
30
|
+
|
|
31
|
+
# Sinais de feedback detectados na resposta do usuário (pesos)
|
|
32
|
+
FEEDBACK_SIGNALS = {
|
|
33
|
+
# Negativos (indicam insatisfação)
|
|
34
|
+
"refaça": -15,
|
|
35
|
+
"de novo": -15,
|
|
36
|
+
"não era isso": -20,
|
|
37
|
+
"errado": -15,
|
|
38
|
+
"não gostei": -10,
|
|
39
|
+
"muito resumido": -10,
|
|
40
|
+
"faltou": -10,
|
|
41
|
+
"incompleto": -10,
|
|
42
|
+
"onde está": -5,
|
|
43
|
+
"cadê": -5,
|
|
44
|
+
"não tem": -10,
|
|
45
|
+
|
|
46
|
+
# Positivos (indicam satisfação)
|
|
47
|
+
"perfeito": +10,
|
|
48
|
+
"exatamente": +10,
|
|
49
|
+
"ótimo": +5,
|
|
50
|
+
"isso mesmo": +5,
|
|
51
|
+
"obrigado": +3,
|
|
52
|
+
"show": +5,
|
|
53
|
+
"massa": +5,
|
|
54
|
+
"muito bom": +5,
|
|
55
|
+
"excelente": +8,
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# Threshold para sugerir criação de skill (baseado em DETECTION-PROTOCOL.md)
|
|
59
|
+
SKILL_SUGGESTION_THRESHOLD = 3
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
63
|
+
# PATTERN DETECTION
|
|
64
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
65
|
+
|
|
66
|
+
# Categorias de padrão detectáveis
|
|
67
|
+
PATTERN_CATEGORIES = {
|
|
68
|
+
"log_visual": {
|
|
69
|
+
"keywords": ["log bonito", "log visual", "formatar log", "status formatado", "resumo visual"],
|
|
70
|
+
"agent_hint": "chronicler"
|
|
71
|
+
},
|
|
72
|
+
"análise_financeira": {
|
|
73
|
+
"keywords": ["roi", "unit economics", "margem", "lucratividade", "custos", "receita"],
|
|
74
|
+
"agent_hint": "finance-agent"
|
|
75
|
+
},
|
|
76
|
+
"estrutura_time": {
|
|
77
|
+
"keywords": ["time de vendas", "estrutura comercial", "org chart", "organograma", "equipe"],
|
|
78
|
+
"agent_hint": "talent-agent"
|
|
79
|
+
},
|
|
80
|
+
"playbook": {
|
|
81
|
+
"keywords": ["playbook", "manual", "guia", "passo a passo", "tutorial"],
|
|
82
|
+
"agent_hint": None
|
|
83
|
+
},
|
|
84
|
+
"comparação": {
|
|
85
|
+
"keywords": ["compare", "diferença entre", "versus", "vs", "comparar"],
|
|
86
|
+
"agent_hint": None
|
|
87
|
+
},
|
|
88
|
+
"conselho": {
|
|
89
|
+
"keywords": ["conselho", "council", "debate", "war room", "múltiplas perspectivas"],
|
|
90
|
+
"agent_hint": "council"
|
|
91
|
+
},
|
|
92
|
+
"dna_extração": {
|
|
93
|
+
"keywords": ["extrair dna", "dna cognitivo", "filosofias", "frameworks", "metodologias"],
|
|
94
|
+
"agent_hint": "extract-dna"
|
|
95
|
+
},
|
|
96
|
+
"processo_inbox": {
|
|
97
|
+
"keywords": ["processar inbox", "processar arquivos", "pipeline", "batch"],
|
|
98
|
+
"agent_hint": "process-inbox"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def detect_feedback_signal(response: str) -> Dict:
|
|
104
|
+
"""
|
|
105
|
+
Detecta sinais de feedback na resposta do usuário.
|
|
106
|
+
|
|
107
|
+
Aprende INDIRETAMENTE - não pergunta se gostou, detecta pelos sinais.
|
|
108
|
+
"""
|
|
109
|
+
response_lower = response.lower()
|
|
110
|
+
|
|
111
|
+
signals_found = []
|
|
112
|
+
total_score = 0
|
|
113
|
+
|
|
114
|
+
for signal, weight in FEEDBACK_SIGNALS.items():
|
|
115
|
+
if signal in response_lower:
|
|
116
|
+
signals_found.append({"signal": signal, "weight": weight})
|
|
117
|
+
total_score += weight
|
|
118
|
+
|
|
119
|
+
# Sinal implícito: resposta curta sem reclamação = aceitação
|
|
120
|
+
word_count = len(response.split())
|
|
121
|
+
if word_count < 10 and not signals_found:
|
|
122
|
+
signals_found.append({"signal": "implicit_acceptance", "weight": 5})
|
|
123
|
+
total_score += 5
|
|
124
|
+
|
|
125
|
+
# Sinal implícito: resposta muito longa com correções = insatisfação
|
|
126
|
+
if word_count > 50 and any(s["weight"] < 0 for s in signals_found):
|
|
127
|
+
total_score -= 5 # Penalidade adicional
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
"signals": signals_found,
|
|
131
|
+
"total_score": total_score,
|
|
132
|
+
"sentiment": "positive" if total_score > 0 else "negative" if total_score < 0 else "neutral",
|
|
133
|
+
"word_count": word_count
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def track_request_pattern(prompt: str) -> Dict:
|
|
138
|
+
"""
|
|
139
|
+
Rastreia padrão de request para detecção de skills potenciais.
|
|
140
|
+
|
|
141
|
+
Usa scoring baseado em DETECTION-PROTOCOL.md existente.
|
|
142
|
+
"""
|
|
143
|
+
pattern_scores = defaultdict(int)
|
|
144
|
+
prompt_lower = prompt.lower()
|
|
145
|
+
|
|
146
|
+
matched_keywords = []
|
|
147
|
+
|
|
148
|
+
for pattern_name, config in PATTERN_CATEGORIES.items():
|
|
149
|
+
for kw in config["keywords"]:
|
|
150
|
+
if kw in prompt_lower:
|
|
151
|
+
pattern_scores[pattern_name] += 1
|
|
152
|
+
matched_keywords.append({"pattern": pattern_name, "keyword": kw})
|
|
153
|
+
|
|
154
|
+
if pattern_scores:
|
|
155
|
+
top_pattern = max(pattern_scores, key=pattern_scores.get)
|
|
156
|
+
return {
|
|
157
|
+
"detected_pattern": top_pattern,
|
|
158
|
+
"score": pattern_scores[top_pattern],
|
|
159
|
+
"all_scores": dict(pattern_scores),
|
|
160
|
+
"matched_keywords": matched_keywords,
|
|
161
|
+
"agent_hint": PATTERN_CATEGORIES.get(top_pattern, {}).get("agent_hint")
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
"detected_pattern": None,
|
|
166
|
+
"score": 0,
|
|
167
|
+
"all_scores": {},
|
|
168
|
+
"matched_keywords": [],
|
|
169
|
+
"agent_hint": None
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
174
|
+
# SKILL SUGGESTION
|
|
175
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
176
|
+
|
|
177
|
+
def should_suggest_skill(pattern: str) -> Dict:
|
|
178
|
+
"""
|
|
179
|
+
Verifica se deve sugerir criação de skill baseado no padrão.
|
|
180
|
+
|
|
181
|
+
Threshold do DETECTION-PROTOCOL: ≥ 3 ocorrências do mesmo padrão.
|
|
182
|
+
"""
|
|
183
|
+
# Conta ocorrências recentes do padrão
|
|
184
|
+
recent_count = count_recent_pattern_occurrences(pattern, days=7)
|
|
185
|
+
|
|
186
|
+
if recent_count >= SKILL_SUGGESTION_THRESHOLD:
|
|
187
|
+
return {
|
|
188
|
+
"suggest": True,
|
|
189
|
+
"pattern": pattern,
|
|
190
|
+
"occurrences": recent_count,
|
|
191
|
+
"threshold": SKILL_SUGGESTION_THRESHOLD,
|
|
192
|
+
"message": f"Pattern '{pattern}' detected {recent_count} times. Consider creating a skill."
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
"suggest": False,
|
|
197
|
+
"pattern": pattern,
|
|
198
|
+
"occurrences": recent_count,
|
|
199
|
+
"threshold": SKILL_SUGGESTION_THRESHOLD,
|
|
200
|
+
"remaining": SKILL_SUGGESTION_THRESHOLD - recent_count
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def count_recent_pattern_occurrences(pattern: str, days: int = 7) -> int:
|
|
205
|
+
"""Conta ocorrências recentes de um padrão no log."""
|
|
206
|
+
if not PATTERNS_LOG.exists():
|
|
207
|
+
return 0
|
|
208
|
+
|
|
209
|
+
count = 0
|
|
210
|
+
cutoff = datetime.now().timestamp() - (days * 24 * 60 * 60)
|
|
211
|
+
|
|
212
|
+
try:
|
|
213
|
+
with open(PATTERNS_LOG, "r", encoding='utf-8') as f:
|
|
214
|
+
for line in f:
|
|
215
|
+
if line.strip():
|
|
216
|
+
entry = json.loads(line)
|
|
217
|
+
entry_time = datetime.fromisoformat(entry.get("timestamp", "2000-01-01")).timestamp()
|
|
218
|
+
if entry_time >= cutoff and entry.get("pattern") == pattern:
|
|
219
|
+
count += 1
|
|
220
|
+
except Exception:
|
|
221
|
+
pass
|
|
222
|
+
|
|
223
|
+
return count
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def create_skill_suggestion(pattern: str, occurrences: int) -> Dict:
|
|
227
|
+
"""Cria sugestão de skill para o usuário."""
|
|
228
|
+
suggestion = {
|
|
229
|
+
"suggestion_id": f"SKILL-SUG-{datetime.now().strftime('%Y%m%d-%H%M%S')}",
|
|
230
|
+
"timestamp": datetime.now().isoformat(),
|
|
231
|
+
"pattern": pattern,
|
|
232
|
+
"occurrences": occurrences,
|
|
233
|
+
"suggested_name": pattern.replace("_", "-"),
|
|
234
|
+
"suggested_keywords": PATTERN_CATEGORIES.get(pattern, {}).get("keywords", []),
|
|
235
|
+
"status": "pending",
|
|
236
|
+
"created_skill": None
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
# Salva sugestão
|
|
240
|
+
SKILL_SUGGESTIONS_LOG.parent.mkdir(parents=True, exist_ok=True)
|
|
241
|
+
try:
|
|
242
|
+
with open(SKILL_SUGGESTIONS_LOG, "a", encoding='utf-8') as f:
|
|
243
|
+
f.write(json.dumps(suggestion, ensure_ascii=False) + "\n")
|
|
244
|
+
except Exception:
|
|
245
|
+
pass
|
|
246
|
+
|
|
247
|
+
return suggestion
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
251
|
+
# PREFERENCE LEARNING
|
|
252
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
253
|
+
|
|
254
|
+
def learn_preference(feedback_info: Dict, context: str, agent: str = None) -> Dict:
|
|
255
|
+
"""
|
|
256
|
+
Aprende preferência baseado no feedback detectado.
|
|
257
|
+
|
|
258
|
+
Não pergunta - aprende silenciosamente.
|
|
259
|
+
"""
|
|
260
|
+
preference = {
|
|
261
|
+
"timestamp": datetime.now().isoformat(),
|
|
262
|
+
"context_preview": context[:100] if context else "",
|
|
263
|
+
"agent": agent,
|
|
264
|
+
"signals": feedback_info.get("signals", []),
|
|
265
|
+
"sentiment": feedback_info.get("sentiment", "neutral"),
|
|
266
|
+
"score": feedback_info.get("total_score", 0)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
# Extrai aprendizados específicos
|
|
270
|
+
if feedback_info.get("sentiment") == "negative":
|
|
271
|
+
preference["learned"] = extract_negative_learning(feedback_info, context)
|
|
272
|
+
elif feedback_info.get("sentiment") == "positive":
|
|
273
|
+
preference["learned"] = extract_positive_learning(feedback_info, context)
|
|
274
|
+
else:
|
|
275
|
+
preference["learned"] = None
|
|
276
|
+
|
|
277
|
+
# Salva preferência
|
|
278
|
+
log_preference(preference)
|
|
279
|
+
|
|
280
|
+
return preference
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def extract_negative_learning(feedback: Dict, context: str) -> Dict:
|
|
284
|
+
"""Extrai aprendizado de feedback negativo."""
|
|
285
|
+
signals = [s["signal"] for s in feedback.get("signals", [])]
|
|
286
|
+
|
|
287
|
+
learning = {
|
|
288
|
+
"type": "negative",
|
|
289
|
+
"issues": []
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if "muito resumido" in signals or "incompleto" in signals or "faltou" in signals:
|
|
293
|
+
learning["issues"].append("output_too_short")
|
|
294
|
+
learning["preference"] = "user prefers more detailed outputs"
|
|
295
|
+
|
|
296
|
+
if "errado" in signals or "não era isso" in signals:
|
|
297
|
+
learning["issues"].append("misunderstood_request")
|
|
298
|
+
learning["preference"] = "need better request interpretation"
|
|
299
|
+
|
|
300
|
+
if "refaça" in signals or "de novo" in signals:
|
|
301
|
+
learning["issues"].append("quality_insufficient")
|
|
302
|
+
learning["preference"] = "user has high quality standards"
|
|
303
|
+
|
|
304
|
+
return learning
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def extract_positive_learning(feedback: Dict, context: str) -> Dict:
|
|
308
|
+
"""Extrai aprendizado de feedback positivo."""
|
|
309
|
+
return {
|
|
310
|
+
"type": "positive",
|
|
311
|
+
"validated": "current approach is working",
|
|
312
|
+
"continue": True
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def log_preference(preference: Dict):
|
|
317
|
+
"""Loga preferência aprendida."""
|
|
318
|
+
PREFERENCES_LOG.parent.mkdir(parents=True, exist_ok=True)
|
|
319
|
+
|
|
320
|
+
try:
|
|
321
|
+
with open(PREFERENCES_LOG, "a", encoding='utf-8') as f:
|
|
322
|
+
f.write(json.dumps(preference, ensure_ascii=False) + "\n")
|
|
323
|
+
except Exception:
|
|
324
|
+
pass
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
328
|
+
# PATTERN LOGGING
|
|
329
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
330
|
+
|
|
331
|
+
def log_pattern(prompt: str, pattern_info: Dict):
|
|
332
|
+
"""Loga padrão detectado."""
|
|
333
|
+
PATTERNS_LOG.parent.mkdir(parents=True, exist_ok=True)
|
|
334
|
+
|
|
335
|
+
entry = {
|
|
336
|
+
"timestamp": datetime.now().isoformat(),
|
|
337
|
+
"prompt_preview": prompt[:100] if prompt else "",
|
|
338
|
+
"pattern": pattern_info.get("detected_pattern"),
|
|
339
|
+
"score": pattern_info.get("score", 0),
|
|
340
|
+
"matched_keywords": pattern_info.get("matched_keywords", []),
|
|
341
|
+
"agent_hint": pattern_info.get("agent_hint")
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
try:
|
|
345
|
+
with open(PATTERNS_LOG, "a", encoding='utf-8') as f:
|
|
346
|
+
f.write(json.dumps(entry, ensure_ascii=False) + "\n")
|
|
347
|
+
except Exception:
|
|
348
|
+
pass
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
352
|
+
# MAIN INTERFACE
|
|
353
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
354
|
+
|
|
355
|
+
def analyze_prompt(prompt: str) -> Dict:
|
|
356
|
+
"""
|
|
357
|
+
Analisa prompt para padrões e retorna contexto enriquecido.
|
|
358
|
+
|
|
359
|
+
Interface principal para integração com user_prompt_submit.py
|
|
360
|
+
"""
|
|
361
|
+
pattern_info = track_request_pattern(prompt)
|
|
362
|
+
|
|
363
|
+
result = {
|
|
364
|
+
"timestamp": datetime.now().isoformat(),
|
|
365
|
+
"pattern": pattern_info,
|
|
366
|
+
"skill_suggestion": None
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
# Log pattern
|
|
370
|
+
if pattern_info.get("detected_pattern"):
|
|
371
|
+
log_pattern(prompt, pattern_info)
|
|
372
|
+
|
|
373
|
+
# Verifica se deve sugerir skill
|
|
374
|
+
skill_check = should_suggest_skill(pattern_info["detected_pattern"])
|
|
375
|
+
if skill_check.get("suggest"):
|
|
376
|
+
suggestion = create_skill_suggestion(
|
|
377
|
+
pattern_info["detected_pattern"],
|
|
378
|
+
skill_check["occurrences"]
|
|
379
|
+
)
|
|
380
|
+
result["skill_suggestion"] = suggestion
|
|
381
|
+
|
|
382
|
+
return result
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def analyze_response(user_response: str, original_context: str, agent: str = None) -> Dict:
|
|
386
|
+
"""
|
|
387
|
+
Analisa resposta do usuário para feedback implícito.
|
|
388
|
+
|
|
389
|
+
Interface para aprendizado de preferências.
|
|
390
|
+
"""
|
|
391
|
+
feedback = detect_feedback_signal(user_response)
|
|
392
|
+
|
|
393
|
+
result = {
|
|
394
|
+
"timestamp": datetime.now().isoformat(),
|
|
395
|
+
"feedback": feedback
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
# Aprende se há sinal claro
|
|
399
|
+
if feedback.get("sentiment") != "neutral":
|
|
400
|
+
preference = learn_preference(feedback, original_context, agent)
|
|
401
|
+
result["preference_learned"] = preference
|
|
402
|
+
|
|
403
|
+
return result
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
407
|
+
# STATISTICS
|
|
408
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
409
|
+
|
|
410
|
+
def get_pattern_statistics(days: int = 30) -> Dict:
|
|
411
|
+
"""Retorna estatísticas de padrões detectados."""
|
|
412
|
+
if not PATTERNS_LOG.exists():
|
|
413
|
+
return {"total": 0, "by_pattern": {}}
|
|
414
|
+
|
|
415
|
+
stats = defaultdict(int)
|
|
416
|
+
total = 0
|
|
417
|
+
cutoff = datetime.now().timestamp() - (days * 24 * 60 * 60)
|
|
418
|
+
|
|
419
|
+
try:
|
|
420
|
+
with open(PATTERNS_LOG, "r", encoding='utf-8') as f:
|
|
421
|
+
for line in f:
|
|
422
|
+
if line.strip():
|
|
423
|
+
entry = json.loads(line)
|
|
424
|
+
entry_time = datetime.fromisoformat(entry.get("timestamp", "2000-01-01")).timestamp()
|
|
425
|
+
if entry_time >= cutoff:
|
|
426
|
+
pattern = entry.get("pattern")
|
|
427
|
+
if pattern:
|
|
428
|
+
stats[pattern] += 1
|
|
429
|
+
total += 1
|
|
430
|
+
except Exception:
|
|
431
|
+
pass
|
|
432
|
+
|
|
433
|
+
return {
|
|
434
|
+
"total": total,
|
|
435
|
+
"days": days,
|
|
436
|
+
"by_pattern": dict(stats),
|
|
437
|
+
"top_patterns": sorted(stats.items(), key=lambda x: x[1], reverse=True)[:5]
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
def get_preference_statistics(days: int = 30) -> Dict:
|
|
442
|
+
"""Retorna estatísticas de preferências aprendidas."""
|
|
443
|
+
if not PREFERENCES_LOG.exists():
|
|
444
|
+
return {"total": 0, "positive": 0, "negative": 0, "neutral": 0}
|
|
445
|
+
|
|
446
|
+
stats = {"positive": 0, "negative": 0, "neutral": 0}
|
|
447
|
+
total = 0
|
|
448
|
+
cutoff = datetime.now().timestamp() - (days * 24 * 60 * 60)
|
|
449
|
+
|
|
450
|
+
try:
|
|
451
|
+
with open(PREFERENCES_LOG, "r", encoding='utf-8') as f:
|
|
452
|
+
for line in f:
|
|
453
|
+
if line.strip():
|
|
454
|
+
entry = json.loads(line)
|
|
455
|
+
entry_time = datetime.fromisoformat(entry.get("timestamp", "2000-01-01")).timestamp()
|
|
456
|
+
if entry_time >= cutoff:
|
|
457
|
+
sentiment = entry.get("sentiment", "neutral")
|
|
458
|
+
stats[sentiment] = stats.get(sentiment, 0) + 1
|
|
459
|
+
total += 1
|
|
460
|
+
except Exception:
|
|
461
|
+
pass
|
|
462
|
+
|
|
463
|
+
return {
|
|
464
|
+
"total": total,
|
|
465
|
+
"days": days,
|
|
466
|
+
**stats,
|
|
467
|
+
"satisfaction_rate": f"{(stats['positive'] / total * 100):.1f}%" if total > 0 else "N/A"
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
472
|
+
# CLI INTERFACE
|
|
473
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
474
|
+
|
|
475
|
+
if __name__ == "__main__":
|
|
476
|
+
import sys
|
|
477
|
+
|
|
478
|
+
if len(sys.argv) > 1:
|
|
479
|
+
command = sys.argv[1]
|
|
480
|
+
|
|
481
|
+
if command == "stats":
|
|
482
|
+
print("Pattern Statistics (30 days):")
|
|
483
|
+
stats = get_pattern_statistics()
|
|
484
|
+
print(f" Total patterns: {stats['total']}")
|
|
485
|
+
print(f" Top patterns: {stats['top_patterns']}")
|
|
486
|
+
|
|
487
|
+
print("\nPreference Statistics (30 days):")
|
|
488
|
+
pref_stats = get_preference_statistics()
|
|
489
|
+
print(f" Total: {pref_stats['total']}")
|
|
490
|
+
print(f" Positive: {pref_stats['positive']}")
|
|
491
|
+
print(f" Negative: {pref_stats['negative']}")
|
|
492
|
+
print(f" Satisfaction: {pref_stats['satisfaction_rate']}")
|
|
493
|
+
|
|
494
|
+
elif command == "test":
|
|
495
|
+
test_prompt = " ".join(sys.argv[2:]) if len(sys.argv) > 2 else "me dá um log bonito visual"
|
|
496
|
+
print(f"Testing prompt: {test_prompt}\n")
|
|
497
|
+
|
|
498
|
+
result = analyze_prompt(test_prompt)
|
|
499
|
+
print(f"Pattern detected: {result['pattern'].get('detected_pattern')}")
|
|
500
|
+
print(f"Score: {result['pattern'].get('score')}")
|
|
501
|
+
print(f"Agent hint: {result['pattern'].get('agent_hint')}")
|
|
502
|
+
|
|
503
|
+
if result.get('skill_suggestion'):
|
|
504
|
+
print(f"\nSkill suggestion: {result['skill_suggestion']}")
|
|
505
|
+
|
|
506
|
+
else:
|
|
507
|
+
print("Usage:")
|
|
508
|
+
print(" python pattern_analyzer.py stats - Show statistics")
|
|
509
|
+
print(" python pattern_analyzer.py test <prompt> - Test pattern detection")
|
|
510
|
+
|
|
511
|
+
else:
|
|
512
|
+
# Demo mode
|
|
513
|
+
print("Pattern Analyzer - Layer 3 Demo\n")
|
|
514
|
+
|
|
515
|
+
test_prompts = [
|
|
516
|
+
"me dá um log bonito do Hormozi",
|
|
517
|
+
"qual o ROI do projeto?",
|
|
518
|
+
"compare Cole Gordon com Jeremy Miner",
|
|
519
|
+
"preciso de um playbook de vendas"
|
|
520
|
+
]
|
|
521
|
+
|
|
522
|
+
for prompt in test_prompts:
|
|
523
|
+
result = analyze_prompt(prompt)
|
|
524
|
+
pattern = result['pattern'].get('detected_pattern', 'None')
|
|
525
|
+
score = result['pattern'].get('score', 0)
|
|
526
|
+
print(f"'{prompt[:40]}...' -> Pattern: {pattern}, Score: {score}")
|