@robbiesrobotics/alice-agents 1.5.8 → 1.5.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +152 -129
- package/bin/alice-install.mjs +27 -35
- package/lib/hermes-agent.mjs +449 -0
- package/lib/hermes-installer.mjs +338 -0
- package/lib/installer.mjs +254 -19
- package/lib/skills.mjs +128 -4
- package/package.json +3 -3
- package/templates/skills/acculynx/SKILL.md +183 -0
- package/templates/skills/acculynx/references/analysis_template.py +116 -0
- package/templates/skills/acculynx/references/dashboard_page.tsx +641 -0
- package/templates/skills/claude-code/SKILL.md +2 -2
- package/templates/skills/coding-agent/SKILL.md +68 -0
- package/templates/skills/crawl4ai/SKILL.md +119 -0
- package/templates/skills/crawl4ai/scripts/crwl +3 -0
- package/templates/workspaces/_shared/AGENTS-hermes.md +54 -0
- package/templates/workspaces/_shared/AGENTS.md +25 -0
- package/templates/workspaces/_shared/SOUL-hermes.md +35 -0
- package/templates/workspaces/_shared/hermes-agent-skill.md +40 -0
- package/templates/workspaces/_shared/hermes-orchestrator-skill.md +150 -0
- package/templates/workspaces/_shared/hermes-specialist-skill.md +109 -0
- package/templates/workspaces/accuscope/AGENTS.md +38 -0
- package/templates/workspaces/accuscope/FEEDBACK.md +27 -0
- package/templates/workspaces/accuscope/HEARTBEAT.md +26 -0
- package/templates/workspaces/accuscope/IDENTITY.md +48 -0
- package/templates/workspaces/accuscope/LEARNINGS.md +46 -0
- package/templates/workspaces/accuscope/MEMORY.md +47 -0
- package/templates/workspaces/accuscope/PLAYBOOK.md +65 -0
- package/templates/workspaces/accuscope/SOUL.md +40 -0
- package/templates/workspaces/accuscope/TOOLS.md +63 -0
- package/templates/workspaces/accuscope/USER.md +39 -0
- package/templates/workspaces/aiden/AGENTS.md +52 -0
- package/templates/workspaces/aiden/FEEDBACK.md +12 -0
- package/templates/workspaces/aiden/HEARTBEAT.md +9 -0
- package/templates/workspaces/aiden/IDENTITY.md +6 -0
- package/templates/workspaces/aiden/LEARNINGS.md +6 -0
- package/templates/workspaces/aiden/MEMORY.md +22 -0
- package/templates/workspaces/aiden/PLAYBOOK.md +16 -0
- package/templates/workspaces/aiden/SOUL.md +1 -1
- package/templates/workspaces/aiden/USER.md +17 -0
- package/templates/workspaces/alex/AGENTS.md +52 -0
- package/templates/workspaces/alex/FEEDBACK.md +11 -0
- package/templates/workspaces/alex/HEARTBEAT.md +9 -0
- package/templates/workspaces/alex/IDENTITY.md +6 -0
- package/templates/workspaces/alex/LEARNINGS.md +5 -0
- package/templates/workspaces/alex/MEMORY.md +22 -0
- package/templates/workspaces/alex/PLAYBOOK.md +16 -0
- package/templates/workspaces/alex/SOUL.md +1 -1
- package/templates/workspaces/alex/USER.md +13 -0
- package/templates/workspaces/aria/AGENTS.md +18 -0
- package/templates/workspaces/aria/FEEDBACK.md +12 -0
- package/templates/workspaces/aria/HEARTBEAT.md +32 -0
- package/templates/workspaces/aria/IDENTITY.md +12 -0
- package/templates/workspaces/aria/LEARNINGS.md +31 -0
- package/templates/workspaces/aria/MEMORY.md +29 -0
- package/templates/workspaces/aria/PLAYBOOK.md +71 -0
- package/templates/workspaces/aria/SOUL.md +57 -0
- package/templates/workspaces/aria/TOOLS.md +47 -0
- package/templates/workspaces/aria/USER.md +18 -0
- package/templates/workspaces/audrey/AGENTS.md +59 -0
- package/templates/workspaces/audrey/FEEDBACK.md +11 -0
- package/templates/workspaces/audrey/HEARTBEAT.md +9 -0
- package/templates/workspaces/audrey/IDENTITY.md +6 -0
- package/templates/workspaces/audrey/LEARNINGS.md +5 -0
- package/templates/workspaces/audrey/MEMORY.md +22 -0
- package/templates/workspaces/audrey/PLAYBOOK.md +16 -0
- package/templates/workspaces/audrey/SOUL.md +1 -1
- package/templates/workspaces/audrey/TOOLS.md +15 -0
- package/templates/workspaces/audrey/USER.md +13 -0
- package/templates/workspaces/avery/AGENTS.md +52 -0
- package/templates/workspaces/avery/FEEDBACK.md +12 -0
- package/templates/workspaces/avery/HEARTBEAT.md +5 -0
- package/templates/workspaces/avery/IDENTITY.md +6 -0
- package/templates/workspaces/avery/LEARNINGS.md +6 -0
- package/templates/workspaces/avery/MEMORY.md +22 -0
- package/templates/workspaces/avery/PLAYBOOK.md +16 -0
- package/templates/workspaces/avery/SOUL.md +1 -1
- package/templates/workspaces/avery/USER.md +17 -0
- package/templates/workspaces/avery/skills/claude-code/SKILL.md +38 -0
- package/templates/workspaces/avery/skills/claude-code/claude_code +55 -0
- package/templates/workspaces/caleb/AGENTS.md +52 -0
- package/templates/workspaces/caleb/FEEDBACK.md +11 -0
- package/templates/workspaces/caleb/HEARTBEAT.md +9 -0
- package/templates/workspaces/caleb/IDENTITY.md +6 -0
- package/templates/workspaces/caleb/LEARNINGS.md +5 -0
- package/templates/workspaces/caleb/MEMORY.md +22 -0
- package/templates/workspaces/caleb/PLAYBOOK.md +16 -0
- package/templates/workspaces/caleb/SOUL.md +1 -1
- package/templates/workspaces/caleb/TOOLS.md +30 -0
- package/templates/workspaces/caleb/USER.md +13 -0
- package/templates/workspaces/clara/AGENTS.md +59 -0
- package/templates/workspaces/clara/FEEDBACK.md +12 -0
- package/templates/workspaces/clara/HEARTBEAT.md +5 -0
- package/templates/workspaces/clara/IDENTITY.md +6 -0
- package/templates/workspaces/clara/LEARNINGS.md +6 -0
- package/templates/workspaces/clara/MEMORY.md +22 -0
- package/templates/workspaces/clara/PLAYBOOK.md +16 -0
- package/templates/workspaces/clara/SOUL.md +1 -1
- package/templates/workspaces/clara/TOOLS.md +15 -0
- package/templates/workspaces/clara/USER.md +17 -0
- package/templates/workspaces/daphne/AGENTS.md +59 -0
- package/templates/workspaces/daphne/FEEDBACK.md +18 -0
- package/templates/workspaces/daphne/HEARTBEAT.md +5 -0
- package/templates/workspaces/daphne/IDENTITY.md +6 -0
- package/templates/workspaces/daphne/LEARNINGS.md +6 -0
- package/templates/workspaces/daphne/MEMORY.md +22 -0
- package/templates/workspaces/daphne/PLAYBOOK.md +48 -0
- package/templates/workspaces/daphne/SOUL.md +1 -1
- package/templates/workspaces/daphne/TOOLS.md +15 -0
- package/templates/workspaces/daphne/USER.md +17 -0
- package/templates/workspaces/darius/AGENTS.md +52 -0
- package/templates/workspaces/darius/FEEDBACK.md +12 -0
- package/templates/workspaces/darius/HEARTBEAT.md +5 -0
- package/templates/workspaces/darius/IDENTITY.md +6 -0
- package/templates/workspaces/darius/LEARNINGS.md +6 -0
- package/templates/workspaces/darius/MEMORY.md +22 -0
- package/templates/workspaces/darius/PLAYBOOK.md +16 -0
- package/templates/workspaces/darius/SOUL.md +1 -1
- package/templates/workspaces/darius/USER.md +17 -0
- package/templates/workspaces/darius/skills/claude-code/SKILL.md +38 -0
- package/templates/workspaces/darius/skills/claude-code/claude_code +55 -0
- package/templates/workspaces/devon/AGENTS.md +52 -0
- package/templates/workspaces/devon/FEEDBACK.md +11 -0
- package/templates/workspaces/devon/HEARTBEAT.md +5 -0
- package/templates/workspaces/devon/IDENTITY.md +6 -0
- package/templates/workspaces/devon/LEARNINGS.md +11 -0
- package/templates/workspaces/devon/MEMORY.md +22 -0
- package/templates/workspaces/devon/PLAYBOOK.md +16 -0
- package/templates/workspaces/devon/SOUL.md +1 -1
- package/templates/workspaces/devon/USER.md +13 -0
- package/templates/workspaces/devon/check_github.py +12 -0
- package/templates/workspaces/devon/check_mc_env.py +30 -0
- package/templates/workspaces/devon/check_sb.py +34 -0
- package/templates/workspaces/devon/check_vercel.py +12 -0
- package/templates/workspaces/devon/get_mc_files.py +17 -0
- package/templates/workspaces/devon/write_heartbeat.py +67 -0
- package/templates/workspaces/dylan/.env.example +33 -0
- package/templates/workspaces/dylan/00007_verify_licenses_table.sql +100 -0
- package/templates/workspaces/dylan/AGENTS.md +52 -0
- package/templates/workspaces/dylan/FEEDBACK.md +28 -0
- package/templates/workspaces/dylan/HEARTBEAT.md +5 -0
- package/templates/workspaces/dylan/IDENTITY.md +6 -0
- package/templates/workspaces/dylan/LEARNINGS.md +70 -0
- package/templates/workspaces/dylan/MEMORY.md +22 -0
- package/templates/workspaces/dylan/PLAYBOOK.md +16 -0
- package/templates/workspaces/dylan/SOUL.md +1 -1
- package/templates/workspaces/dylan/STRIPE_PIPELINE.md +185 -0
- package/templates/workspaces/dylan/USER.md +17 -0
- package/templates/workspaces/dylan/n8n-stripe-welcome-workflow.json +123 -0
- package/templates/workspaces/dylan/skills/claude-code/SKILL.md +38 -0
- package/templates/workspaces/dylan/skills/claude-code/claude_code +55 -0
- package/templates/workspaces/dylan/stripe-webhook-handler.py +433 -0
- package/templates/workspaces/dylan/test_mock_webhook.py +103 -0
- package/templates/workspaces/elena/AGENTS.md +59 -0
- package/templates/workspaces/elena/FEEDBACK.md +11 -0
- package/templates/workspaces/elena/HEARTBEAT.md +9 -0
- package/templates/workspaces/elena/IDENTITY.md +6 -0
- package/templates/workspaces/elena/LEARNINGS.md +5 -0
- package/templates/workspaces/elena/MEMORY.md +22 -0
- package/templates/workspaces/elena/PLAYBOOK.md +16 -0
- package/templates/workspaces/elena/SOUL.md +1 -1
- package/templates/workspaces/elena/TOOLS.md +15 -0
- package/templates/workspaces/elena/USER.md +13 -0
- package/templates/workspaces/eva/AGENTS.md +59 -0
- package/templates/workspaces/eva/FEEDBACK.md +11 -0
- package/templates/workspaces/eva/HEARTBEAT.md +9 -0
- package/templates/workspaces/eva/IDENTITY.md +6 -0
- package/templates/workspaces/eva/LEARNINGS.md +5 -0
- package/templates/workspaces/eva/MEMORY.md +22 -0
- package/templates/workspaces/eva/PLAYBOOK.md +16 -0
- package/templates/workspaces/eva/SOUL.md +1 -1
- package/templates/workspaces/eva/TOOLS.md +15 -0
- package/templates/workspaces/eva/USER.md +13 -0
- package/templates/workspaces/felix/AGENTS.md +52 -0
- package/templates/workspaces/felix/FEEDBACK.md +11 -0
- package/templates/workspaces/felix/HEARTBEAT.md +5 -0
- package/templates/workspaces/felix/IDENTITY.md +6 -0
- package/templates/workspaces/felix/LEARNINGS.md +17 -0
- package/templates/workspaces/felix/MEMORY.md +22 -0
- package/templates/workspaces/felix/PLAYBOOK.md +16 -0
- package/templates/workspaces/felix/SOUL.md +1 -1
- package/templates/workspaces/felix/USER.md +13 -0
- package/templates/workspaces/felix/fidelia-psychology.html +1594 -0
- package/templates/workspaces/felix/task.txt +164 -0
- package/templates/workspaces/hannah/AGENTS.md +59 -0
- package/templates/workspaces/hannah/FEEDBACK.md +12 -0
- package/templates/workspaces/hannah/HEARTBEAT.md +5 -0
- package/templates/workspaces/hannah/IDENTITY.md +6 -0
- package/templates/workspaces/hannah/LEARNINGS.md +6 -0
- package/templates/workspaces/hannah/MEMORY.md +22 -0
- package/templates/workspaces/hannah/PLAYBOOK.md +16 -0
- package/templates/workspaces/hannah/SOUL.md +1 -1
- package/templates/workspaces/hannah/TOOLS.md +15 -0
- package/templates/workspaces/hannah/USER.md +17 -0
- package/templates/workspaces/isaac/AGENTS.md +52 -0
- package/templates/workspaces/isaac/FEEDBACK.md +12 -0
- package/templates/workspaces/isaac/HEARTBEAT.md +9 -0
- package/templates/workspaces/isaac/IDENTITY.md +6 -0
- package/templates/workspaces/isaac/LEARNINGS.md +6 -0
- package/templates/workspaces/isaac/MEMORY.md +22 -0
- package/templates/workspaces/isaac/PLAYBOOK.md +16 -0
- package/templates/workspaces/isaac/SOUL.md +1 -1
- package/templates/workspaces/isaac/USER.md +17 -0
- package/templates/workspaces/isaac/skills/claude-code/SKILL.md +38 -0
- package/templates/workspaces/isaac/skills/claude-code/claude_code +55 -0
- package/templates/workspaces/logan/AGENTS.md +59 -0
- package/templates/workspaces/logan/FEEDBACK.md +11 -0
- package/templates/workspaces/logan/HEARTBEAT.md +9 -0
- package/templates/workspaces/logan/IDENTITY.md +6 -0
- package/templates/workspaces/logan/LEARNINGS.md +5 -0
- package/templates/workspaces/logan/MEMORY.md +22 -0
- package/templates/workspaces/logan/PLAYBOOK.md +16 -0
- package/templates/workspaces/logan/SOUL.md +1 -1
- package/templates/workspaces/logan/TOOLS.md +15 -0
- package/templates/workspaces/logan/USER.md +13 -0
- package/templates/workspaces/maxxipro/AGENTS.md +29 -0
- package/templates/workspaces/maxxipro/FEEDBACK.md +19 -0
- package/templates/workspaces/maxxipro/HEARTBEAT.md +22 -0
- package/templates/workspaces/maxxipro/IDENTITY.md +35 -0
- package/templates/workspaces/maxxipro/KNOWLEDGE.md +335 -0
- package/templates/workspaces/maxxipro/LEARNINGS.md +47 -0
- package/templates/workspaces/maxxipro/MEMORY.md +60 -0
- package/templates/workspaces/maxxipro/OUTREACH_TEMPLATES.md +143 -0
- package/templates/workspaces/maxxipro/PLAYBOOK.md +81 -0
- package/templates/workspaces/maxxipro/SOUL.md +146 -0
- package/templates/workspaces/maxxipro/TOOLS.md +81 -0
- package/templates/workspaces/maxxipro/USER.md +40 -0
- package/templates/workspaces/morgan/AGENTS.md +59 -0
- package/templates/workspaces/morgan/FEEDBACK.md +19 -0
- package/templates/workspaces/morgan/HEARTBEAT.md +5 -0
- package/templates/workspaces/morgan/IDENTITY.md +6 -0
- package/templates/workspaces/morgan/LEARNINGS.md +18 -0
- package/templates/workspaces/morgan/MEMORY.md +22 -0
- package/templates/workspaces/morgan/PLAYBOOK.md +16 -0
- package/templates/workspaces/morgan/SOUL.md +1 -1
- package/templates/workspaces/morgan/TOOLS.md +15 -0
- package/templates/workspaces/morgan/USER.md +13 -0
- package/templates/workspaces/nadia/AGENTS.md +59 -0
- package/templates/workspaces/nadia/FEEDBACK.md +12 -0
- package/templates/workspaces/nadia/HEARTBEAT.md +5 -0
- package/templates/workspaces/nadia/IDENTITY.md +6 -0
- package/templates/workspaces/nadia/LEARNINGS.md +6 -0
- package/templates/workspaces/nadia/MEMORY.md +22 -0
- package/templates/workspaces/nadia/PLAYBOOK.md +16 -0
- package/templates/workspaces/nadia/SOUL.md +1 -1
- package/templates/workspaces/nadia/TOOLS.md +15 -0
- package/templates/workspaces/nadia/USER.md +13 -0
- package/templates/workspaces/nate/AGENTS.md +24 -0
- package/templates/workspaces/nate/FEEDBACK.md +12 -0
- package/templates/workspaces/nate/HEARTBEAT.md +33 -0
- package/templates/workspaces/nate/IDENTITY.md +15 -0
- package/templates/workspaces/nate/LEARNINGS.md +33 -0
- package/templates/workspaces/nate/MEMORY.md +39 -0
- package/templates/workspaces/nate/PLAYBOOK.md +160 -0
- package/templates/workspaces/nate/SOUL.md +50 -0
- package/templates/workspaces/nate/TOOLS.md +111 -0
- package/templates/workspaces/nate/USER.md +32 -0
- package/templates/workspaces/olivia/.last-openclaw-version +1 -0
- package/templates/workspaces/olivia/.npmrc.tmp +0 -0
- package/templates/workspaces/olivia/AGENTS.md +77 -0
- package/templates/workspaces/olivia/ALPHA_CODING_BENCHMARK.txt +148 -0
- package/templates/workspaces/olivia/ALPHA_MODEL_GUIDE.md +393 -0
- package/templates/workspaces/olivia/FEEDBACK.md +13 -0
- package/templates/workspaces/olivia/HEADTOHEAD_BENCHMARK.txt +1289 -0
- package/templates/workspaces/olivia/HEARTBEAT.md +267 -0
- package/templates/workspaces/olivia/IDENTITY.md +6 -0
- package/templates/workspaces/olivia/LEARNINGS.md +708 -0
- package/templates/workspaces/olivia/MEMORY.md +202 -0
- package/templates/workspaces/olivia/MISSION_CONTROL_DESIGN_SPEC_v1.md +1143 -0
- package/templates/workspaces/olivia/MVP-COMPLETION-SUMMARY.md +175 -0
- package/templates/workspaces/olivia/NETWORK_IMPLEMENTATION_PLAN.md +1556 -0
- package/templates/workspaces/olivia/NEW_NODES_BENCHMARK.txt +947 -0
- package/templates/workspaces/olivia/PLAYBOOK.md +42 -0
- package/templates/workspaces/olivia/SELF-HEALING-COMPLETE.md +150 -0
- package/templates/workspaces/olivia/SOUL.md +8 -8
- package/templates/workspaces/olivia/TOOLS.md +15 -0
- package/templates/workspaces/olivia/USER.md +17 -0
- package/templates/workspaces/olivia/alicefleet-supabase-credentials.md +50 -0
- package/templates/workspaces/olivia/dzombo-copy-rewrite.md +115 -0
- package/templates/workspaces/olivia/dzombo-implementation-plan.md +1248 -0
- package/templates/workspaces/olivia/fidelia-psychology.html +1594 -0
- package/templates/workspaces/olivia/lead_debug.png +0 -0
- package/templates/workspaces/olivia/minimatch-10.2.4.tgz +0 -0
- package/templates/workspaces/olivia/operation-bllm-research.md +157 -0
- package/templates/workspaces/olivia/qa-audit-mission-control-v2.md +538 -0
- package/templates/workspaces/olivia/roofmaxx_logo.svg +1 -0
- package/templates/workspaces/olivia/roofmaxx_social.jpg +0 -0
- package/templates/workspaces/olivia/skills/1password/SKILL.md +53 -0
- package/templates/workspaces/olivia/skills/1password/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/afrexai-recruiting-engine/README.md +57 -0
- package/templates/workspaces/olivia/skills/afrexai-recruiting-engine/SKILL.md +534 -0
- package/templates/workspaces/olivia/skills/afrexai-recruiting-engine/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/agent-security/SKILL.md +69 -0
- package/templates/workspaces/olivia/skills/agent-security/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/agentic-security-audit/SKILL.md +855 -0
- package/templates/workspaces/olivia/skills/agentic-security-audit/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/ai-automation-consulting/SKILL.md +67 -0
- package/templates/workspaces/olivia/skills/ai-automation-consulting/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/ai-automation-consulting/skill.json +12 -0
- package/templates/workspaces/olivia/skills/ai-presentation-maker/SKILL.md +1104 -0
- package/templates/workspaces/olivia/skills/ai-presentation-maker/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/ai-productivity-audit/SKILL.md +181 -0
- package/templates/workspaces/olivia/skills/ai-productivity-audit/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/ai-researcher/README.md +31 -0
- package/templates/workspaces/olivia/skills/ai-researcher/SKILL.md +59 -0
- package/templates/workspaces/olivia/skills/ai-researcher/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/ai-seo-writer/README.md +19 -0
- package/templates/workspaces/olivia/skills/ai-seo-writer/SKILL.md +100 -0
- package/templates/workspaces/olivia/skills/ai-seo-writer/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/analytics-tracking-2/SKILL.md +309 -0
- package/templates/workspaces/olivia/skills/analytics-tracking-2/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/api-doc-writer/SKILL.md +232 -0
- package/templates/workspaces/olivia/skills/api-doc-writer/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/api-generator/SKILL.md +49 -0
- package/templates/workspaces/olivia/skills/api-generator/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/api-generator/tips.md +10 -0
- package/templates/workspaces/olivia/skills/apple-notes/SKILL.md +50 -0
- package/templates/workspaces/olivia/skills/apple-notes/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/apple-reminders/SKILL.md +67 -0
- package/templates/workspaces/olivia/skills/apple-reminders/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/automation-workflows/SKILL.md +267 -0
- package/templates/workspaces/olivia/skills/automation-workflows/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/autoresearch/SKILL.md +46 -0
- package/templates/workspaces/olivia/skills/autoresearch/aria_write.py +148 -0
- package/templates/workspaces/olivia/skills/autoresearch/autoresearch.py +75 -0
- package/templates/workspaces/olivia/skills/azure-devops/SKILL.md +115 -0
- package/templates/workspaces/olivia/skills/azure-devops/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/blogwatcher/SKILL.md +46 -0
- package/templates/workspaces/olivia/skills/blogwatcher/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/blucli/SKILL.md +27 -0
- package/templates/workspaces/olivia/skills/blucli/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/check-analytics/SKILL.md +92 -0
- package/templates/workspaces/olivia/skills/check-analytics/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/cloud-architect/SKILL.md +89 -0
- package/templates/workspaces/olivia/skills/cloud-architect/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/cloud-infra-automation/SKILL.md +50 -0
- package/templates/workspaces/olivia/skills/cloud-infra-automation/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/cloud-storage/SKILL.md +61 -0
- package/templates/workspaces/olivia/skills/cloud-storage/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/cloud-storage/auth.md +97 -0
- package/templates/workspaces/olivia/skills/cloud-storage/costs.md +88 -0
- package/templates/workspaces/olivia/skills/cloud-storage/providers.md +55 -0
- package/templates/workspaces/olivia/skills/copywriting-pro/SKILL.md +107 -0
- package/templates/workspaces/olivia/skills/copywriting-pro/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/data-analyst-pro/SKILL.md +21 -0
- package/templates/workspaces/olivia/skills/data-analyst-pro/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/database-designer/README.md +388 -0
- package/templates/workspaces/olivia/skills/database-designer/SKILL.md +66 -0
- package/templates/workspaces/olivia/skills/database-designer/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/database-designer/index_optimizer.py +926 -0
- package/templates/workspaces/olivia/skills/database-designer/migration_generator.py +1199 -0
- package/templates/workspaces/olivia/skills/database-designer/schema_analyzer.py +982 -0
- package/templates/workspaces/olivia/skills/deploy-agent/SKILL.md +255 -0
- package/templates/workspaces/olivia/skills/deploy-agent/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/devops-automation-pack/SKILL.md +72 -0
- package/templates/workspaces/olivia/skills/devops-automation-pack/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/devops-automation-pack/deploy.sh +0 -0
- package/templates/workspaces/olivia/skills/financial-analysis-agent/SKILL.md +489 -0
- package/templates/workspaces/olivia/skills/financial-analysis-agent/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/gdpr-compliance-tracker/README.md +72 -0
- package/templates/workspaces/olivia/skills/gdpr-compliance-tracker/SKILL.md +226 -0
- package/templates/workspaces/olivia/skills/gdpr-compliance-tracker/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/gifgrep/SKILL.md +47 -0
- package/templates/workspaces/olivia/skills/gifgrep/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/github/SKILL.md +47 -0
- package/templates/workspaces/olivia/skills/github/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/gog/SKILL.md +36 -0
- package/templates/workspaces/olivia/skills/gog/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/growth-strategy-hub/SKILL.md +135 -0
- package/templates/workspaces/olivia/skills/growth-strategy-hub/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/growth-strategy-hub/metadata.json +4 -0
- package/templates/workspaces/olivia/skills/hetzner-cloud/SKILL.md +130 -0
- package/templates/workspaces/olivia/skills/hetzner-cloud/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/himalaya/SKILL.md +217 -0
- package/templates/workspaces/olivia/skills/himalaya/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/hotel-recommendation/SKILL.md +117 -0
- package/templates/workspaces/olivia/skills/hotel-recommendation/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/hr-policy-generator/SKILL.md +54 -0
- package/templates/workspaces/olivia/skills/hr-policy-generator/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/human-writing/SKILL.md +41 -0
- package/templates/workspaces/olivia/skills/human-writing/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/imsg/SKILL.md +25 -0
- package/templates/workspaces/olivia/skills/imsg/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/in-depth-research/SKILL.md +124 -0
- package/templates/workspaces/olivia/skills/in-depth-research/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/in-depth-research/methodology.md +75 -0
- package/templates/workspaces/olivia/skills/in-depth-research/output-formats.md +168 -0
- package/templates/workspaces/olivia/skills/in-depth-research/sources.md +80 -0
- package/templates/workspaces/olivia/skills/javascript-skills/README.md +71 -0
- package/templates/workspaces/olivia/skills/javascript-skills/SKILL.md +746 -0
- package/templates/workspaces/olivia/skills/javascript-skills/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/leadership-strategy-playbook/SKILL.md +147 -0
- package/templates/workspaces/olivia/skills/leadership-strategy-playbook/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/market-research-agent/README.md +29 -0
- package/templates/workspaces/olivia/skills/market-research-agent/SKILL.md +52 -0
- package/templates/workspaces/olivia/skills/market-research-agent/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/marketing-analytics/SKILL.md +74 -0
- package/templates/workspaces/olivia/skills/marketing-analytics/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/marketing-master-io/SKILL.md +125 -0
- package/templates/workspaces/olivia/skills/marketing-master-io/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/marketing-strategy-pmm/SKILL.md +398 -0
- package/templates/workspaces/olivia/skills/marketing-strategy-pmm/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/meta-ads-analytics/SKILL.md +53 -0
- package/templates/workspaces/olivia/skills/meta-ads-analytics/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/obsidian/SKILL.md +55 -0
- package/templates/workspaces/olivia/skills/obsidian/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/openclaw-accounting/SKILL.md +125 -0
- package/templates/workspaces/olivia/skills/openclaw-accounting/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/openclaw-security-toolkit/CHANGELOG.md +35 -0
- package/templates/workspaces/olivia/skills/openclaw-security-toolkit/CHANNELLOG.md +73 -0
- package/templates/workspaces/olivia/skills/openclaw-security-toolkit/README.md +161 -0
- package/templates/workspaces/olivia/skills/openclaw-security-toolkit/SKILL.md +130 -0
- package/templates/workspaces/olivia/skills/openclaw-security-toolkit/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/openclaw-security-toolkit/config.json +36 -0
- package/templates/workspaces/olivia/skills/openclaw-security-toolkit/metadata.json +19 -0
- package/templates/workspaces/olivia/skills/openhue/SKILL.md +30 -0
- package/templates/workspaces/olivia/skills/openhue/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/orgx-operations-agent/SKILL.md +41 -0
- package/templates/workspaces/olivia/skills/orgx-operations-agent/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/outreach/SKILL.md +84 -0
- package/templates/workspaces/olivia/skills/outreach/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/outreach/by-type.md +166 -0
- package/templates/workspaces/olivia/skills/outreach/templates.md +154 -0
- package/templates/workspaces/olivia/skills/outreach/tracking.md +145 -0
- package/templates/workspaces/olivia/skills/persona-hr-coordinator/SKILL.md +38 -0
- package/templates/workspaces/olivia/skills/persona-hr-coordinator/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/personal-productivity/SKILL.md +161 -0
- package/templates/workspaces/olivia/skills/personal-productivity/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/personal-productivity/index.js +363 -0
- package/templates/workspaces/olivia/skills/personal-productivity/package.json +15 -0
- package/templates/workspaces/olivia/skills/personal-travel/README.md +34 -0
- package/templates/workspaces/olivia/skills/personal-travel/SKILL.md +46 -0
- package/templates/workspaces/olivia/skills/personal-travel/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/presentation-html-generator-skill/SKILL.md +185 -0
- package/templates/workspaces/olivia/skills/presentation-html-generator-skill/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/product-manager/SKILL.md +77 -0
- package/templates/workspaces/olivia/skills/product-manager/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/quant-strategy/SKILL.md +28 -0
- package/templates/workspaces/olivia/skills/quant-strategy/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/sales-pipeline-tracker/README.md +29 -0
- package/templates/workspaces/olivia/skills/sales-pipeline-tracker/SKILL.md +45 -0
- package/templates/workspaces/olivia/skills/sales-pipeline-tracker/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/security-auditor/SKILL.md +399 -0
- package/templates/workspaces/olivia/skills/security-auditor/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/security-hardening/SKILL.md +296 -0
- package/templates/workspaces/olivia/skills/security-hardening/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/security-scanner/SKILL.md +67 -0
- package/templates/workspaces/olivia/skills/security-scanner/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/seo-optimization/SKILL.md +31 -0
- package/templates/workspaces/olivia/skills/seo-optimization/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/service-booking/SKILL.md +193 -0
- package/templates/workspaces/olivia/skills/service-booking/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/sme-hr-automation/SKILL.md +131 -0
- package/templates/workspaces/olivia/skills/sme-hr-automation/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/social-media-scheduler/README.md +29 -0
- package/templates/workspaces/olivia/skills/social-media-scheduler/SKILL.md +49 -0
- package/templates/workspaces/olivia/skills/social-media-scheduler/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/sonoscli/SKILL.md +26 -0
- package/templates/workspaces/olivia/skills/sonoscli/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/strategy-advisor/SKILL.md +33 -0
- package/templates/workspaces/olivia/skills/strategy-advisor/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/summarize/SKILL.md +49 -0
- package/templates/workspaces/olivia/skills/summarize/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/things-mac/SKILL.md +61 -0
- package/templates/workspaces/olivia/skills/things-mac/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/travel-itinerary-planner/SKILL.md +121 -0
- package/templates/workspaces/olivia/skills/travel-itinerary-planner/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/travel-manager/SKILL.md +36 -0
- package/templates/workspaces/olivia/skills/travel-manager/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/travel-planning/SKILL.md +238 -0
- package/templates/workspaces/olivia/skills/travel-planning/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/travel-planning/booking-guide.md +91 -0
- package/templates/workspaces/olivia/skills/travel-planning/memory-template.md +111 -0
- package/templates/workspaces/olivia/skills/travel-planning/multi-city.md +131 -0
- package/templates/workspaces/olivia/skills/travel-planning/packing-templates.md +155 -0
- package/templates/workspaces/olivia/skills/travel-planning/setup.md +66 -0
- package/templates/workspaces/olivia/skills/update-it-all/SKILL.md +143 -0
- package/templates/workspaces/olivia/skills/update-it-all/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/voice/SKILL.md +62 -0
- package/templates/workspaces/olivia/skills/weather/SKILL.md +49 -0
- package/templates/workspaces/olivia/skills/weather/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/web-researcher/SKILL.md +21 -0
- package/templates/workspaces/olivia/skills/web-researcher/_meta.json +6 -0
- package/templates/workspaces/olivia/skills/website-seo/SKILL.md +284 -0
- package/templates/workspaces/olivia/skills/website-seo/_meta.json +6 -0
- package/templates/workspaces/olivia/stripe-welcome-n8n.json +103 -0
- package/templates/workspaces/olivia/test2.wav.wav +0 -0
- package/templates/workspaces/olivia/test_speech.json +1 -0
- package/templates/workspaces/olivia/test_speech.srt +0 -0
- package/templates/workspaces/olivia/test_speech.tsv +1 -0
- package/templates/workspaces/olivia/test_speech.txt +0 -0
- package/templates/workspaces/olivia/test_speech.vtt +2 -0
- package/templates/workspaces/owen/AGENTS.md +59 -0
- package/templates/workspaces/owen/FEEDBACK.md +12 -0
- package/templates/workspaces/owen/HEARTBEAT.md +5 -0
- package/templates/workspaces/owen/IDENTITY.md +6 -0
- package/templates/workspaces/owen/LEARNINGS.md +46 -0
- package/templates/workspaces/owen/MEMORY.md +22 -0
- package/templates/workspaces/owen/PLAYBOOK.md +16 -0
- package/templates/workspaces/owen/SOUL.md +1 -1
- package/templates/workspaces/owen/TOOLS.md +15 -0
- package/templates/workspaces/owen/USER.md +17 -0
- package/templates/workspaces/parker/AGENTS.md +59 -0
- package/templates/workspaces/parker/FEEDBACK.md +11 -0
- package/templates/workspaces/parker/HEARTBEAT.md +5 -0
- package/templates/workspaces/parker/IDENTITY.md +6 -0
- package/templates/workspaces/parker/LEARNINGS.md +17 -0
- package/templates/workspaces/parker/MEMORY.md +22 -0
- package/templates/workspaces/parker/PLAYBOOK.md +16 -0
- package/templates/workspaces/parker/SOUL.md +1 -1
- package/templates/workspaces/parker/TOOLS.md +15 -0
- package/templates/workspaces/parker/USER.md +13 -0
- package/templates/workspaces/quinn/AGENTS.md +52 -0
- package/templates/workspaces/quinn/FEEDBACK.md +11 -0
- package/templates/workspaces/quinn/HEARTBEAT.md +5 -0
- package/templates/workspaces/quinn/IDENTITY.md +6 -0
- package/templates/workspaces/quinn/LEARNINGS.md +35 -0
- package/templates/workspaces/quinn/MEMORY.md +22 -0
- package/templates/workspaces/quinn/PLAYBOOK.md +16 -0
- package/templates/workspaces/quinn/SOUL.md +1 -1
- package/templates/workspaces/quinn/USER.md +17 -0
- package/templates/workspaces/quinn/alice-login-page.png +0 -0
- package/templates/workspaces/rowan/AGENTS.md +59 -0
- package/templates/workspaces/rowan/FEEDBACK.md +12 -0
- package/templates/workspaces/rowan/HEARTBEAT.md +5 -0
- package/templates/workspaces/rowan/IDENTITY.md +6 -0
- package/templates/workspaces/rowan/LEARNINGS.md +12 -0
- package/templates/workspaces/rowan/MEMORY.md +22 -0
- package/templates/workspaces/rowan/PLAYBOOK.md +16 -0
- package/templates/workspaces/rowan/SOUL.md +1 -1
- package/templates/workspaces/rowan/USER.md +17 -0
- package/templates/workspaces/selena/AGENTS.md +59 -0
- package/templates/workspaces/selena/FEEDBACK.md +12 -0
- package/templates/workspaces/selena/HEARTBEAT.md +5 -0
- package/templates/workspaces/selena/IDENTITY.md +6 -0
- package/templates/workspaces/selena/LEARNINGS.md +24 -0
- package/templates/workspaces/selena/MEMORY.md +22 -0
- package/templates/workspaces/selena/PLAYBOOK.md +16 -0
- package/templates/workspaces/selena/SOUL.md +1 -1
- package/templates/workspaces/selena/USER.md +17 -0
- package/templates/workspaces/selena/kids-ai-security-compliance-plan.md +791 -0
- package/templates/workspaces/selena/kidspark-coppa-compliance-audit.md +866 -0
- package/templates/workspaces/sloane/AGENTS.md +59 -0
- package/templates/workspaces/sloane/FEEDBACK.md +12 -0
- package/templates/workspaces/sloane/HEARTBEAT.md +9 -0
- package/templates/workspaces/sloane/IDENTITY.md +6 -0
- package/templates/workspaces/sloane/LEARNINGS.md +6 -0
- package/templates/workspaces/sloane/MEMORY.md +22 -0
- package/templates/workspaces/sloane/PLAYBOOK.md +16 -0
- package/templates/workspaces/sloane/SOUL.md +1 -1
- package/templates/workspaces/sloane/TOOLS.md +15 -0
- package/templates/workspaces/sloane/USER.md +13 -0
- package/templates/workspaces/smoketestagent/AGENTS.md +52 -0
- package/templates/workspaces/smoketestagent/FEEDBACK.md +3 -0
- package/templates/workspaces/smoketestagent/HEARTBEAT.md +14 -0
- package/templates/workspaces/smoketestagent/IDENTITY.md +6 -0
- package/templates/workspaces/smoketestagent/LEARNINGS.md +3 -0
- package/templates/workspaces/smoketestagent/MEMORY.md +24 -0
- package/templates/workspaces/smoketestagent/PLAYBOOK.md +7 -0
- package/templates/workspaces/smoketestagent/SOUL.md +32 -0
- package/templates/workspaces/smoketestagent/TOOLS.md +13 -0
- package/templates/workspaces/smoketestagent/USER.md +5 -0
- package/templates/workspaces/sophie/AGENTS.md +59 -0
- package/templates/workspaces/sophie/FEEDBACK.md +12 -0
- package/templates/workspaces/sophie/HEARTBEAT.md +9 -0
- package/templates/workspaces/sophie/IDENTITY.md +6 -0
- package/templates/workspaces/sophie/LEARNINGS.md +6 -0
- package/templates/workspaces/sophie/MEMORY.md +22 -0
- package/templates/workspaces/sophie/PLAYBOOK.md +16 -0
- package/templates/workspaces/sophie/SOUL.md +1 -1
- package/templates/workspaces/sophie/TOOLS.md +15 -0
- package/templates/workspaces/sophie/USER.md +17 -0
- package/templates/workspaces/tommy/AGENTS.md +59 -0
- package/templates/workspaces/tommy/FEEDBACK.md +12 -0
- package/templates/workspaces/tommy/HEARTBEAT.md +9 -0
- package/templates/workspaces/tommy/IDENTITY.md +6 -0
- package/templates/workspaces/tommy/LEARNINGS.md +6 -0
- package/templates/workspaces/tommy/MEMORY.md +22 -0
- package/templates/workspaces/tommy/PLAYBOOK.md +16 -0
- package/templates/workspaces/tommy/SOUL.md +1 -1
- package/templates/workspaces/tommy/TOOLS.md +15 -0
- package/templates/workspaces/tommy/USER.md +17 -0
- package/templates/workspaces/uma/AGENTS.md +59 -0
- package/templates/workspaces/uma/FEEDBACK.md +11 -0
- package/templates/workspaces/uma/HEARTBEAT.md +5 -0
- package/templates/workspaces/uma/IDENTITY.md +6 -0
- package/templates/workspaces/uma/LEARNINGS.md +11 -0
- package/templates/workspaces/uma/MEMORY.md +22 -0
- package/templates/workspaces/uma/PLAYBOOK.md +16 -0
- package/templates/workspaces/uma/SOUL.md +1 -1
- package/templates/workspaces/uma/TOOLS.md +15 -0
- package/templates/workspaces/uma/USER.md +13 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "A.L.I.C.E. — Stripe Welcome Email",
|
|
3
|
+
"nodes": [
|
|
4
|
+
{
|
|
5
|
+
"parameters": {
|
|
6
|
+
"httpMethod": "POST",
|
|
7
|
+
"path": "stripe-checkout-completed",
|
|
8
|
+
"responseMode": "onReceived",
|
|
9
|
+
"options": { "rawBody": false }
|
|
10
|
+
},
|
|
11
|
+
"id": "stripe-webhook-trigger",
|
|
12
|
+
"name": "Stripe Checkout Completed Webhook",
|
|
13
|
+
"type": "n8n-nodes-base.webhook",
|
|
14
|
+
"typeVersion": 2,
|
|
15
|
+
"position": [250, 300],
|
|
16
|
+
"webhookId": "stripe-welcome-webhook"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"parameters": {
|
|
20
|
+
"jsCode": "// Parse incoming webhook payload from stripe-webhook-handler.py\nconst body = $input.item.json;\n\nconst licenseKey = body.license_key;\nconst email = body.email;\nconst plan = body.plan || 'pro';\nconst ingestToken = body.ingest_token || '';\nconst workerToken = body.worker_token || '';\nconst aliceCloudToken = body.alice_cloud_token || ingestToken;\nconst purchasedAt = body.purchased_at || new Date().toISOString();\n\n// Build activation command\nconst activationCmd = ingestToken\n ? `npx @robbiesrobotics/alice-agents --license ${licenseKey} --cloud --cloud-token ${ingestToken} --cloud-worker-token ${workerToken}`\n : `npx @robbiesrobotics/alice-agents --license ${licenseKey}`;\n\nreturn {\n json: {\n licenseKey,\n email,\n plan,\n ingestToken,\n workerToken,\n aliceCloudToken,\n activationCmd,\n purchasedAt,\n hasTokens: Boolean(ingestToken),\n }\n};"
|
|
21
|
+
},
|
|
22
|
+
"id": "parse-payload",
|
|
23
|
+
"name": "Parse Payload",
|
|
24
|
+
"type": "n8n-nodes-base.code",
|
|
25
|
+
"typeVersion": 2,
|
|
26
|
+
"position": [480, 300]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"parameters": {
|
|
30
|
+
"conditions": {
|
|
31
|
+
"options": { "fallbackOutputs": [] },
|
|
32
|
+
"conditions": [
|
|
33
|
+
{
|
|
34
|
+
"id": "has-email",
|
|
35
|
+
"leftValue": "={{ $json.email }}",
|
|
36
|
+
"rightValue": "",
|
|
37
|
+
"operator": { "type": "string", "operation": "isNotEmpty" }
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
"options": {}
|
|
42
|
+
},
|
|
43
|
+
"id": "check-email",
|
|
44
|
+
"name": "Validate Email",
|
|
45
|
+
"type": "n8n-nodes-base.if",
|
|
46
|
+
"typeVersion": 2,
|
|
47
|
+
"position": [710, 300]
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"parameters": {
|
|
51
|
+
"method": "POST",
|
|
52
|
+
"url": "=https://api.resend.com/emails",
|
|
53
|
+
"authentication": "genericCredentialType",
|
|
54
|
+
"genericAuthType": "httpHeaderAuth",
|
|
55
|
+
"sendHeaders": true,
|
|
56
|
+
"headerParameters": {
|
|
57
|
+
"parameters": [
|
|
58
|
+
{ "name": "Authorization", "value": "Bearer {{ $env.RESEND_API_KEY }}" },
|
|
59
|
+
{ "name": "Content-Type", "value": "application/json" }
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
"sendBody": true,
|
|
63
|
+
"bodyParameters": {
|
|
64
|
+
"parameters": [
|
|
65
|
+
{ "name": "from", "value": "A.L.I.C.E. <hello@av3.ai>" },
|
|
66
|
+
{ "name": "to", "value": "={{ $json.email }}" },
|
|
67
|
+
{ "name": "subject", "value": "Your A.L.I.C.E. Pro License Key" },
|
|
68
|
+
{ "name": "html", "value": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\"/>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/>\n <title>Welcome to A.L.I.C.E. — Robbie's Robotics</title>\n <style>\n body { margin: 0; padding: 0; background-color: #0f0f14; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; color: #e2e8f0; }\n .wrapper { max-width: 620px; margin: 0 auto; padding: 40px 20px; }\n .logo { text-align: center; margin-bottom: 32px; }\n .logo-text { font-size: 22px; font-weight: 700; color: #a78bfa; letter-spacing: 0.05em; }\n .card { background: #1a1a2e; border: 1px solid #2d2d4e; border-radius: 12px; padding: 36px 40px; margin-bottom: 24px; }\n h1 { font-size: 28px; font-weight: 700; color: #f1f5f9; margin: 0 0 8px 0; }\n .subtitle { color: #94a3b8; font-size: 16px; margin-bottom: 28px; }\n .divider { border: none; border-top: 1px solid #2d2d4e; margin: 28px 0; }\n h2 { font-size: 16px; font-weight: 600; color: #a78bfa; text-transform: uppercase; letter-spacing: 0.08em; margin: 0 0 16px 0; }\n .credential-box { background: #0f0f1a; border: 1px solid #3730a3; border-radius: 8px; padding: 16px 20px; margin-bottom: 12px; }\n .credential-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.1em; color: #64748b; margin-bottom: 4px; }\n .credential-value { font-family: 'Courier New', Courier, monospace; font-size: 15px; color: #e2e8f0; word-break: break-all; }\n .step-list { list-style: none; padding: 0; margin: 0; }\n .step-list li { display: flex; align-items: flex-start; gap: 14px; padding: 12px 0; border-bottom: 1px solid #1e1e38; }\n .step-list li:last-child { border-bottom: none; }\n .step-num { background: #4f46e5; color: #fff; border-radius: 50%; width: 26px; height: 26px; min-width: 26px; font-size: 13px; font-weight: 700; text-align: center; line-height: 26px; }\n .step-title { font-weight: 600; font-size: 15px; color: #f1f5f9; margin-bottom: 4px; }\n .step-desc { font-size: 13px; color: #94a3b8; line-height: 1.5; }\n code { background: #0f0f1a; border: 1px solid #2d2d4e; border-radius: 4px; padding: 1px 6px; font-family: monospace; font-size: 12px; color: #a78bfa; }\n .btn { display: inline-block; background: #4f46e5; color: #fff; text-decoration: none; padding: 14px 28px; border-radius: 8px; font-weight: 600; font-size: 15px; }\n .btn-outline { display: inline-block; border: 1px solid #4f46e5; color: #a78bfa; text-decoration: none; padding: 12px 24px; border-radius: 8px; font-weight: 600; font-size: 14px; }\n .cta-row { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 20px; }\n .support-card { background: #0f0f1a; border: 1px solid #2d2d4e; border-radius: 8px; padding: 20px 24px; margin-bottom: 24px; }\n .support-card p { margin: 0; font-size: 14px; color: #94a3b8; line-height: 1.8; }\n .support-card a { color: #a78bfa; text-decoration: none; }\n .footer { text-align: center; font-size: 12px; color: #475569; padding-top: 8px; }\n .footer a { color: #64748b; text-decoration: none; }\n .badge { display: inline-block; background: #14532d; color: #4ade80; font-size: 11px; font-weight: 600; padding: 3px 10px; border-radius: 20px; text-transform: uppercase; letter-spacing: 0.06em; margin-left: 8px; vertical-align: middle; }\n </style>\n</head>\n<body>\n <div class=\"wrapper\">\n <div class=\"logo\"><div class=\"logo-text\">🤖 A.L.I.C.E.</div></div>\n <div class=\"card\">\n <h1>You're in. Welcome aboard. <span class=\"badge\">Active</span></h1>\n <p class=\"subtitle\">Your A.L.I.C.E. subscription is live. Below is everything you need to get started.</p>\n <hr class=\"divider\"/>\n <h2>Your License Key</h2>\n <div class=\"credential-box\">\n <div class=\"credential-label\">License Key</div>\n <div class=\"credential-value\">{{ $json.licenseKey }}</div>\n </div>\n <hr class=\"divider\"/>\n <h2>Cloud Tokens</h2>\n <div class=\"credential-box\">\n <div class=\"credential-label\">A.L.I.C.E. Cloud Token</div>\n <div class=\"credential-value\">{{ $json.aliceCloudToken }}</div>\n </div>\n <hr class=\"divider\"/>\n <h2>Quickstart — 3 Steps</h2>\n <ul class=\"step-list\">\n <li><div class=\"step-num\">1</div><div><div class=\"step-title\">Install OpenClaw</div><div class=\"step-desc\"><code>npm install -g openclaw</code> then <code>openclaw setup</code></div></div></li>\n <li><div class=\"step-num\">2</div><div><div class=\"step-title\">Activate A.L.I.C.E.</div><div class=\"step-desc\"><code>{{ $json.activationCmd }}</code></div></div></li>\n <li><div class=\"step-num\">3</div><div><div class=\"step-title\">First task</div><div class=\"step-desc\">Message Alice: <code>review my open PRs and summarize blockers</code></div></div></li>\n </ul>\n <div class=\"cta-row\">\n <a class=\"btn\" href=\"https://getalice.av3.ai/quickstart\">Quickstart Guide →</a>\n <a class=\"btn-outline\" href=\"https://getalice.av3.ai/dashboard\">Dashboard</a>\n </div>\n </div>\n <div class=\"support-card\">\n <h2>Need Help?</h2>\n <p>📧 <a href=\"mailto:rob@robbiesrobotics.com\">rob@robbiesrobotics.com</a><br/>📅 <a href=\"https://cal.com/robbiesrobotics\">Book onboarding call</a><br/>📖 <a href=\"https://getalice.av3.ai/docs\">Docs</a></p>\n </div>\n <div class=\"footer\"><p>Robbie's Robotics · <a href=\"https://getalice.av3.ai\">getalice.av3.ai</a></p></div>\n </div>\n</body>\n</html>" }
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
"options": {
|
|
72
|
+
"retryOnFail": true,
|
|
73
|
+
"maxTries": 3,
|
|
74
|
+
"waitBetweenTries": 2000
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"id": "send-welcome-email",
|
|
78
|
+
"name": "Send Welcome Email",
|
|
79
|
+
"type": "n8n-nodes-base.httpRequest",
|
|
80
|
+
"typeVersion": 4.2,
|
|
81
|
+
"position": [940, 300]
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"parameters": {
|
|
85
|
+
"jsCode": "// Log success for observability\nconst item = $input.item.json;\nconsole.log('Welcome email sent to:', item.email, '| License:', item.licenseKey);\nreturn [{ json: { sent: true, email: item.email, licenseKey: item.licenseKey } }];"
|
|
86
|
+
},
|
|
87
|
+
"id": "log-success",
|
|
88
|
+
"name": "Log Success",
|
|
89
|
+
"type": "n8n-nodes-base.code",
|
|
90
|
+
"typeVersion": 2,
|
|
91
|
+
"position": [1160, 300]
|
|
92
|
+
}
|
|
93
|
+
],
|
|
94
|
+
"connections": {
|
|
95
|
+
"Stripe Checkout Completed Webhook": {
|
|
96
|
+
"main": [
|
|
97
|
+
[{ "node": "Parse Payload", "type": "main", "index": 0 }]
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
"Parse Payload": {
|
|
101
|
+
"main": [
|
|
102
|
+
[{ "node": "Validate Email", "type": "main", "index": 0 }]
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
"Validate Email": {
|
|
106
|
+
"main": [
|
|
107
|
+
[{ "node": "Send Welcome Email", "type": "main", "index": 0 }],
|
|
108
|
+
[]
|
|
109
|
+
]
|
|
110
|
+
},
|
|
111
|
+
"Send Welcome Email": {
|
|
112
|
+
"main": [
|
|
113
|
+
[{ "node": "Log Success", "type": "main", "index": 0 }]
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"settings": {
|
|
118
|
+
"executionOrder": "v1",
|
|
119
|
+
"saveManualExecutions": true,
|
|
120
|
+
"callerPolicy": "workflowsFromSameOwner",
|
|
121
|
+
"errorWorkflow": ""
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Claude Code
|
|
2
|
+
|
|
3
|
+
Delegate coding tasks to the Claude Code CLI for autonomous code generation, editing, debugging, refactoring, and analysis. Claude Code runs with its own built-in tools (file editing, terminal, web search) and returns results directly.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- Writing new code or features
|
|
8
|
+
- Debugging failing tests or errors
|
|
9
|
+
- Refactoring existing code
|
|
10
|
+
- Code review and analysis
|
|
11
|
+
- Complex multi-file changes
|
|
12
|
+
- Any task where you need to read, write, or execute code
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
claude_code "Write a Python function that sorts a list of dictionaries by a given key"
|
|
18
|
+
claude_code "Debug the failing test in tests/unit/test_auth.py" "/path/to/project"
|
|
19
|
+
claude_code "Refactor the database module to use async" "/path/to/project" "max"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Parameters
|
|
23
|
+
|
|
24
|
+
1. **task** (required) — Clear description of the coding task. Be specific about what files, languages, and outcomes you expect.
|
|
25
|
+
2. **workdir** (optional) — Working directory for Claude Code. Defaults to the agent's workspace. Set this to the project root when working on a specific codebase.
|
|
26
|
+
3. **effort** (optional) — Effort level: `low`, `medium`, `high`, `max`. Defaults to `high`. Use `max` for complex multi-file tasks.
|
|
27
|
+
|
|
28
|
+
## Environment Variables
|
|
29
|
+
|
|
30
|
+
- `CLAUDE_CODE_MAX_BUDGET` — Max USD per invocation (default: `2.00`). Prevents runaway costs.
|
|
31
|
+
- `CLAUDE_CODE_PERMISSION_MODE` — Permission mode (default: `auto`). Options: `auto`, `acceptEdits`, `bypassPermissions`.
|
|
32
|
+
|
|
33
|
+
## Tips
|
|
34
|
+
|
|
35
|
+
- Be specific in your task description — "Fix the bug where login fails with empty password" is better than "fix login"
|
|
36
|
+
- Set workdir to the project root so Claude Code can navigate the full codebase
|
|
37
|
+
- For large refactors, use effort `max`
|
|
38
|
+
- Review Claude Code's output before incorporating it into your response
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# claude_code — OpenClaw skill: delegate coding tasks to Claude Code CLI
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# claude_code <task> [workdir] [effort]
|
|
6
|
+
#
|
|
7
|
+
# Arguments:
|
|
8
|
+
# task — (required) Description of the coding task
|
|
9
|
+
# workdir — (optional) Working directory, defaults to current directory
|
|
10
|
+
# effort — (optional) low|medium|high|max, defaults to high
|
|
11
|
+
#
|
|
12
|
+
# Environment:
|
|
13
|
+
# CLAUDE_CODE_MAX_BUDGET — Max USD per invocation (default: 2.00)
|
|
14
|
+
# CLAUDE_CODE_PERMISSION_MODE — auto|acceptEdits|bypassPermissions (default: auto)
|
|
15
|
+
#
|
|
16
|
+
# This skill runs Claude Code in non-interactive print mode (-p) so it
|
|
17
|
+
# executes autonomously and returns results without user interaction.
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
TASK="${1:?Error: task description is required. Usage: claude_code <task> [workdir] [effort]}"
|
|
21
|
+
WORKDIR="${2:-.}"
|
|
22
|
+
EFFORT="${3:-high}"
|
|
23
|
+
MAX_BUDGET="${CLAUDE_CODE_MAX_BUDGET:-2.00}"
|
|
24
|
+
PERM_MODE="${CLAUDE_CODE_PERMISSION_MODE:-auto}"
|
|
25
|
+
|
|
26
|
+
# Resolve workdir to absolute path
|
|
27
|
+
WORKDIR="$(cd "$WORKDIR" 2>/dev/null && pwd)" || {
|
|
28
|
+
echo "Error: working directory '$2' does not exist."
|
|
29
|
+
exit 1
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# Locate claude binary
|
|
33
|
+
CLAUDE_BIN="${CLAUDE_CODE_BIN:-claude}"
|
|
34
|
+
if ! command -v "$CLAUDE_BIN" &>/dev/null; then
|
|
35
|
+
# Check common install locations
|
|
36
|
+
for candidate in "$HOME/.local/bin/claude" "/usr/local/bin/claude"; do
|
|
37
|
+
if [ -x "$candidate" ]; then
|
|
38
|
+
CLAUDE_BIN="$candidate"
|
|
39
|
+
break
|
|
40
|
+
fi
|
|
41
|
+
done
|
|
42
|
+
if ! command -v "$CLAUDE_BIN" &>/dev/null && [ ! -x "$CLAUDE_BIN" ]; then
|
|
43
|
+
echo "Error: claude CLI not found. Install Claude Code: https://docs.anthropic.com/en/docs/claude-code"
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Run Claude Code in non-interactive print mode
|
|
49
|
+
exec "$CLAUDE_BIN" -p "$TASK" \
|
|
50
|
+
--output-format text \
|
|
51
|
+
--permission-mode "$PERM_MODE" \
|
|
52
|
+
--effort "$EFFORT" \
|
|
53
|
+
--max-budget-usd "$MAX_BUDGET" \
|
|
54
|
+
--no-session-persistence \
|
|
55
|
+
2>&1
|
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
A.L.I.C.E. Stripe Webhook Handler
|
|
4
|
+
Runs on: Ubuntu Desktop (alpha@100.106.110.119)
|
|
5
|
+
Port: 5001 (FLASK_PORT)
|
|
6
|
+
|
|
7
|
+
Handles: checkout.session.completed
|
|
8
|
+
Actions:
|
|
9
|
+
1. Validate Stripe webhook signature
|
|
10
|
+
2. Generate license key (ALICE-XXXX-XXXX-XXXX)
|
|
11
|
+
3. Write to Supabase licenses + teams + team_tokens tables
|
|
12
|
+
4. Trigger n8n welcome email workflow
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
python3 stripe-webhook-handler.py
|
|
16
|
+
|
|
17
|
+
For local testing:
|
|
18
|
+
python3 stripe-webhook-handler.py --test
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import os
|
|
22
|
+
import sys
|
|
23
|
+
import json
|
|
24
|
+
import re
|
|
25
|
+
import hmac
|
|
26
|
+
import hashlib
|
|
27
|
+
import logging
|
|
28
|
+
import argparse
|
|
29
|
+
from datetime import datetime, timezone
|
|
30
|
+
from typing import Optional
|
|
31
|
+
|
|
32
|
+
import stripe
|
|
33
|
+
import supabase
|
|
34
|
+
import requests
|
|
35
|
+
from flask import Flask, request, jsonify
|
|
36
|
+
|
|
37
|
+
# ─── Logging ──────────────────────────────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
logging.basicConfig(
|
|
40
|
+
level=logging.INFO,
|
|
41
|
+
format="%(asctime)s [%(levelname)s] %(name)s — %(message)s",
|
|
42
|
+
handlers=[logging.StreamHandler(sys.stdout)],
|
|
43
|
+
)
|
|
44
|
+
logger = logging.getLogger("stripe-webhook")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# ─── Config ───────────────────────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
def _require_env(name: str) -> str:
|
|
50
|
+
val = os.environ.get(name)
|
|
51
|
+
if not val:
|
|
52
|
+
raise RuntimeError(f"Missing required environment variable: {name}")
|
|
53
|
+
return val
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class Config:
|
|
57
|
+
# Stripe
|
|
58
|
+
STRIPE_SECRET_KEY: str = _require_env("STRIPE_SECRET_KEY")
|
|
59
|
+
STRIPE_WEBHOOK_SECRET: str = _require_env("STRIPE_WEBHOOK_SECRET")
|
|
60
|
+
|
|
61
|
+
# Supabase
|
|
62
|
+
SUPABASE_URL: str = _require_env("SUPABASE_URL")
|
|
63
|
+
SUPABASE_SERVICE_ROLE_KEY: str = _require_env("SUPABASE_SERVICE_ROLE_KEY")
|
|
64
|
+
|
|
65
|
+
# n8n welcome email trigger
|
|
66
|
+
N8N_WEBHOOK_URL: str = _require_env(
|
|
67
|
+
"N8N_WEBHOOK_URL"
|
|
68
|
+
) # e.g. http://100.106.110.119:5678/webhook/stripe-checkout-completed
|
|
69
|
+
|
|
70
|
+
# Flask
|
|
71
|
+
FLASK_PORT: int = int(os.environ.get("FLASK_PORT", "5001"))
|
|
72
|
+
FLASK_HOST: str = os.environ.get("FLASK_HOST", "0.0.0.0")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# ─── App ──────────────────────────────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
app = Flask(__name__)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# ─── License Key Generation ───────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
def generate_license_key() -> str:
|
|
83
|
+
"""Generate an A.L.I.C.E. license key: ALICE-XXXX-XXXX-XXXX"""
|
|
84
|
+
import secrets
|
|
85
|
+
chunks = [secrets.token_hex(2).upper() for _ in range(3)]
|
|
86
|
+
return "ALICE-" + "-".join(chunks)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# ─── Supabase Helpers ─────────────────────────────────────────────────────────
|
|
90
|
+
|
|
91
|
+
def get_supabase_client():
|
|
92
|
+
return supabase.create_client(
|
|
93
|
+
Config.SUPABASE_URL,
|
|
94
|
+
Config.SUPABASE_SERVICE_ROLE_KEY,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def find_existing_license(sb, stripe_session_id: str) -> Optional[dict]:
|
|
99
|
+
"""Check if license already exists for this Stripe session (deduplication)."""
|
|
100
|
+
resp = (
|
|
101
|
+
sb.table("licenses")
|
|
102
|
+
.select("key, email, plan, stripe_session_id")
|
|
103
|
+
.eq("stripe_session_id", stripe_session_id)
|
|
104
|
+
.maybe_single()
|
|
105
|
+
)
|
|
106
|
+
return resp.data
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def insert_license(sb, email: str, plan: str, stripe_session_id: str, stripe_customer_id: Optional[str]):
|
|
110
|
+
"""Insert a new license record and return it."""
|
|
111
|
+
import secrets
|
|
112
|
+
license_key = generate_license_key()
|
|
113
|
+
resp = (
|
|
114
|
+
sb.table("licenses")
|
|
115
|
+
.insert({
|
|
116
|
+
"email": email,
|
|
117
|
+
"plan": plan,
|
|
118
|
+
"stripe_session_id": stripe_session_id,
|
|
119
|
+
"stripe_customer_id": stripe_customer_id,
|
|
120
|
+
"metadata": {"source": "stripe-webhook-handler.py"},
|
|
121
|
+
})
|
|
122
|
+
.execute()
|
|
123
|
+
)
|
|
124
|
+
if not resp.data:
|
|
125
|
+
raise RuntimeError("License insert returned no data")
|
|
126
|
+
# Override the auto-generated key with our deterministic one
|
|
127
|
+
created = resp.data[0]
|
|
128
|
+
upd = sb.table("licenses").update({"key": license_key}).eq("id", created["id"]).execute()
|
|
129
|
+
created["key"] = license_key
|
|
130
|
+
return created
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def provision_team_and_tokens(sb, license_key: str, email: str):
|
|
134
|
+
"""
|
|
135
|
+
Provision a team + ingest/worker tokens for Mission Control.
|
|
136
|
+
Returns (team_id, ingest_token, worker_token) on success, (None, '', '') on failure.
|
|
137
|
+
"""
|
|
138
|
+
import secrets
|
|
139
|
+
|
|
140
|
+
# Slug from email: normalize and append timestamp
|
|
141
|
+
slug_base = re.sub(r"[^a-z0-9]", "-", email.lower())[:50]
|
|
142
|
+
slug = f"{slug_base}-{int(datetime.now(timezone.utc).timestamp())}"
|
|
143
|
+
|
|
144
|
+
team_resp = sb.table("teams").insert({
|
|
145
|
+
"name": f"{email}'s Team",
|
|
146
|
+
"slug": slug,
|
|
147
|
+
"plan": "pro",
|
|
148
|
+
"owner_email": email,
|
|
149
|
+
}).execute()
|
|
150
|
+
|
|
151
|
+
if not team_resp.data:
|
|
152
|
+
logger.warning("Team insert failed — continuing without team tokens")
|
|
153
|
+
return None, "", ""
|
|
154
|
+
|
|
155
|
+
team_id = team_resp.data[0]["id"]
|
|
156
|
+
ingest_token = "mc_ingest_" + secrets.token_hex(32)
|
|
157
|
+
worker_token = "mc_worker_" + secrets.token_hex(32)
|
|
158
|
+
|
|
159
|
+
token_resp = sb.table("team_tokens").insert({
|
|
160
|
+
"team_id": team_id,
|
|
161
|
+
"license_key": license_key,
|
|
162
|
+
"ingest_token": ingest_token,
|
|
163
|
+
"worker_token": worker_token,
|
|
164
|
+
}).execute()
|
|
165
|
+
|
|
166
|
+
if not token_resp.data:
|
|
167
|
+
logger.warning("Token insert failed — continuing without tokens")
|
|
168
|
+
return team_id, "", ""
|
|
169
|
+
|
|
170
|
+
return team_id, ingest_token, worker_token
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
# ─── n8n Welcome Email Trigger ───────────────────────────────────────────────
|
|
174
|
+
|
|
175
|
+
def trigger_n8n_welcome_email(
|
|
176
|
+
license_key: str,
|
|
177
|
+
email: str,
|
|
178
|
+
plan: str,
|
|
179
|
+
ingest_token: str,
|
|
180
|
+
worker_token: str,
|
|
181
|
+
alice_cloud_token: str,
|
|
182
|
+
):
|
|
183
|
+
"""
|
|
184
|
+
POST to the n8n webhook URL to trigger the welcome email workflow.
|
|
185
|
+
n8n will use the template variables to render the full welcome email.
|
|
186
|
+
"""
|
|
187
|
+
payload = {
|
|
188
|
+
"license_key": license_key,
|
|
189
|
+
"email": email,
|
|
190
|
+
"plan": plan,
|
|
191
|
+
"ingest_token": ingest_token,
|
|
192
|
+
"worker_token": worker_token,
|
|
193
|
+
"alice_cloud_token": alice_cloud_token,
|
|
194
|
+
# Timestamp for audit
|
|
195
|
+
"purchased_at": datetime.now(timezone.utc).isoformat(),
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
try:
|
|
199
|
+
resp = requests.post(
|
|
200
|
+
Config.N8N_WEBHOOK_URL,
|
|
201
|
+
json=payload,
|
|
202
|
+
headers={"Content-Type": "application/json"},
|
|
203
|
+
timeout=15,
|
|
204
|
+
)
|
|
205
|
+
resp.raise_for_status()
|
|
206
|
+
logger.info(
|
|
207
|
+
f"n8n welcome email triggered for {email} — status {resp.status_code}"
|
|
208
|
+
)
|
|
209
|
+
return True
|
|
210
|
+
except requests.RequestException as exc:
|
|
211
|
+
logger.error(f"n8n webhook failed: {exc}")
|
|
212
|
+
return False
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
# ─── Stripe Signature Verification ───────────────────────────────────────────
|
|
216
|
+
|
|
217
|
+
def verify_stripe_signature(body: bytes, sig_header: str) -> stripe.Event:
|
|
218
|
+
"""Verify and construct a Stripe event from the raw request body."""
|
|
219
|
+
try:
|
|
220
|
+
event = stripe.Webhook.construct_event(body, sig_header, Config.STRIPE_WEBHOOK_SECRET)
|
|
221
|
+
except stripe.error.SignatureVerificationError as exc:
|
|
222
|
+
logger.warning(f"Stripe signature verification failed: {exc}")
|
|
223
|
+
raise
|
|
224
|
+
return event
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
# ─── Webhook Handler ───────────────────────────────────────────────────────────
|
|
228
|
+
|
|
229
|
+
@app.route("/webhook/stripe", methods=["POST"])
|
|
230
|
+
def handle_stripe_webhook():
|
|
231
|
+
"""Main Stripe webhook endpoint. Expects Stripe-Signature header."""
|
|
232
|
+
|
|
233
|
+
# Get raw body for signature verification
|
|
234
|
+
body = request.get_data()
|
|
235
|
+
sig_header = request.headers.get("Stripe-Signature", "")
|
|
236
|
+
|
|
237
|
+
if not sig_header:
|
|
238
|
+
logger.warning("Missing Stripe-Signature header")
|
|
239
|
+
return jsonify({"error": "Missing Stripe-Signature header"}), 400
|
|
240
|
+
|
|
241
|
+
# Verify signature
|
|
242
|
+
try:
|
|
243
|
+
event = verify_stripe_signature(body, sig_header)
|
|
244
|
+
except Exception:
|
|
245
|
+
return jsonify({"error": "Signature verification failed"}), 400
|
|
246
|
+
|
|
247
|
+
logger.info(f"Received Stripe event: {event.type} (id={event.id})")
|
|
248
|
+
|
|
249
|
+
if event.type != "checkout.session.completed":
|
|
250
|
+
logger.info(f"Ignoring event type: {event.type}")
|
|
251
|
+
return jsonify({"received": True, "ignored": True})
|
|
252
|
+
|
|
253
|
+
session = event.data.object
|
|
254
|
+
|
|
255
|
+
# Extract email
|
|
256
|
+
email = session.get("customer_details", {}).get("email") or session.get("customer_email")
|
|
257
|
+
if not email:
|
|
258
|
+
logger.warning("No email in checkout session")
|
|
259
|
+
return jsonify({"error": "No email in session"}), 400
|
|
260
|
+
|
|
261
|
+
# Extract plan from metadata
|
|
262
|
+
plan = session.metadata.get("plan", "pro") if session.metadata else "pro"
|
|
263
|
+
if plan not in ("pro", "cloud"):
|
|
264
|
+
plan = "pro"
|
|
265
|
+
|
|
266
|
+
stripe_session_id = session.id
|
|
267
|
+
stripe_customer_id = session.customer if isinstance(session.customer, str) else None
|
|
268
|
+
|
|
269
|
+
logger.info(
|
|
270
|
+
f"Processing checkout.completed — email={email} plan={plan} session={stripe_session_id}"
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
sb = get_supabase_client()
|
|
274
|
+
|
|
275
|
+
# Deduplication check
|
|
276
|
+
existing = find_existing_license(sb, stripe_session_id)
|
|
277
|
+
if existing:
|
|
278
|
+
logger.info(f"License already exists for session {stripe_session_id} — skipping")
|
|
279
|
+
return jsonify({"received": True, "deduplicated": True})
|
|
280
|
+
|
|
281
|
+
# Insert license
|
|
282
|
+
try:
|
|
283
|
+
license_record = insert_license(sb, email, plan, stripe_session_id, stripe_customer_id)
|
|
284
|
+
license_key = license_record["key"]
|
|
285
|
+
logger.info(f"License created: {license_key}")
|
|
286
|
+
except Exception as exc:
|
|
287
|
+
logger.error(f"Failed to create license: {exc}")
|
|
288
|
+
return jsonify({"error": "Failed to create license"}), 500
|
|
289
|
+
|
|
290
|
+
# Provision team + tokens
|
|
291
|
+
team_id, ingest_token, worker_token = provision_team_and_tokens(sb, license_key, email)
|
|
292
|
+
|
|
293
|
+
# alice_cloud_token is the ingest token (same concept, different name)
|
|
294
|
+
alice_cloud_token = ingest_token
|
|
295
|
+
|
|
296
|
+
# Trigger n8n welcome email workflow
|
|
297
|
+
n8n_ok = trigger_n8n_welcome_email(
|
|
298
|
+
license_key=license_key,
|
|
299
|
+
email=email,
|
|
300
|
+
plan=plan,
|
|
301
|
+
ingest_token=ingest_token,
|
|
302
|
+
worker_token=worker_token,
|
|
303
|
+
alice_cloud_token=alice_cloud_token,
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
if not n8n_ok:
|
|
307
|
+
logger.warning("n8n trigger failed — email may not be sent")
|
|
308
|
+
|
|
309
|
+
return jsonify({
|
|
310
|
+
"received": True,
|
|
311
|
+
"license_key": license_key,
|
|
312
|
+
"email": email,
|
|
313
|
+
"plan": plan,
|
|
314
|
+
"team_provisioned": team_id is not None,
|
|
315
|
+
"n8n_triggered": n8n_ok,
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
@app.route("/health", methods=["GET"])
|
|
320
|
+
def health():
|
|
321
|
+
"""Health check endpoint."""
|
|
322
|
+
return jsonify({"status": "ok", "service": "stripe-webhook-handler"})
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
# ─── Test / Mock Mode ──────────────────────────────────────────────────────────
|
|
326
|
+
|
|
327
|
+
@app.route("/test/mock-webhook", methods=["POST"])
|
|
328
|
+
def handle_mock_webhook():
|
|
329
|
+
"""
|
|
330
|
+
Internal test endpoint — simulates a checkout.session.completed event
|
|
331
|
+
without Stripe signature validation. DO NOT expose in production.
|
|
332
|
+
"""
|
|
333
|
+
body = request.get_json() or {}
|
|
334
|
+
|
|
335
|
+
email = body.get("email", "test@example.com")
|
|
336
|
+
plan = body.get("plan", "pro")
|
|
337
|
+
|
|
338
|
+
logger.info(f"[MOCK] Processing mock checkout — email={email} plan={plan}")
|
|
339
|
+
|
|
340
|
+
import secrets
|
|
341
|
+
license_key = generate_license_key()
|
|
342
|
+
stripe_session_id = "cs_test_mock_" + secrets.token_hex(16)
|
|
343
|
+
stripe_customer_id = None
|
|
344
|
+
|
|
345
|
+
sb = get_supabase_client()
|
|
346
|
+
|
|
347
|
+
# Check existing
|
|
348
|
+
existing = find_existing_license(sb, stripe_session_id)
|
|
349
|
+
if existing:
|
|
350
|
+
return jsonify({"received": True, "deduplicated": True, "key": existing["key"]})
|
|
351
|
+
|
|
352
|
+
# Insert
|
|
353
|
+
resp = (
|
|
354
|
+
sb.table("licenses")
|
|
355
|
+
.insert({
|
|
356
|
+
"email": email,
|
|
357
|
+
"plan": plan,
|
|
358
|
+
"stripe_session_id": stripe_session_id,
|
|
359
|
+
"stripe_customer_id": stripe_customer_id,
|
|
360
|
+
"metadata": {"source": "stripe-webhook-handler.py:test"},
|
|
361
|
+
})
|
|
362
|
+
.execute()
|
|
363
|
+
)
|
|
364
|
+
created = resp.data[0]
|
|
365
|
+
|
|
366
|
+
# Update with deterministic key
|
|
367
|
+
sb.table("licenses").update({"key": license_key}).eq("id", created["id"]).execute()
|
|
368
|
+
created["key"] = license_key
|
|
369
|
+
|
|
370
|
+
# Provision team + tokens
|
|
371
|
+
team_id, ingest_token, worker_token = provision_team_and_tokens(sb, license_key, email)
|
|
372
|
+
|
|
373
|
+
# Trigger n8n
|
|
374
|
+
alice_cloud_token = ingest_token
|
|
375
|
+
n8n_ok = trigger_n8n_welcome_email(
|
|
376
|
+
license_key=license_key,
|
|
377
|
+
email=email,
|
|
378
|
+
plan=plan,
|
|
379
|
+
ingest_token=ingest_token,
|
|
380
|
+
worker_token=worker_token,
|
|
381
|
+
alice_cloud_token=alice_cloud_token,
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
return jsonify({
|
|
385
|
+
"received": True,
|
|
386
|
+
"license_key": license_key,
|
|
387
|
+
"email": email,
|
|
388
|
+
"plan": plan,
|
|
389
|
+
"team_provisioned": team_id is not None,
|
|
390
|
+
"ingest_token": ingest_token,
|
|
391
|
+
"worker_token": worker_token,
|
|
392
|
+
"n8n_triggered": n8n_ok,
|
|
393
|
+
})
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
# ─── CLI ───────────────────────────────────────────────────────────────────────
|
|
397
|
+
|
|
398
|
+
def main():
|
|
399
|
+
parser = argparse.ArgumentParser(description="A.L.I.C.E. Stripe Webhook Handler")
|
|
400
|
+
parser.add_argument("--test", action="store_true", help="Run in test mode (mock endpoint only)")
|
|
401
|
+
args = parser.parse_args()
|
|
402
|
+
|
|
403
|
+
if args.test:
|
|
404
|
+
logger.info("Starting in TEST mode (no Stripe signature required)")
|
|
405
|
+
# Override to run a simple test server without loading full config
|
|
406
|
+
# (full config still loaded so we can use it)
|
|
407
|
+
|
|
408
|
+
try:
|
|
409
|
+
# Verify config loads before starting server
|
|
410
|
+
_ = Config.STRIPE_SECRET_KEY
|
|
411
|
+
_ = Config.STRIPE_WEBHOOK_SECRET
|
|
412
|
+
_ = Config.SUPABASE_URL
|
|
413
|
+
_ = Config.SUPABASE_SERVICE_ROLE_KEY
|
|
414
|
+
_ = Config.N8N_WEBHOOK_URL
|
|
415
|
+
logger.info("Config validated successfully")
|
|
416
|
+
except RuntimeError as exc:
|
|
417
|
+
logger.error(f"Config error: {exc}")
|
|
418
|
+
logger.error("Copy .env.example to ~/alice-observability/.env and fill in Rob's keys")
|
|
419
|
+
sys.exit(1)
|
|
420
|
+
|
|
421
|
+
logger.info(
|
|
422
|
+
f"Starting Flask server on {Config.FLASK_HOST}:{Config.FLASK_PORT}"
|
|
423
|
+
)
|
|
424
|
+
app.run(
|
|
425
|
+
host=Config.FLASK_HOST,
|
|
426
|
+
port=Config.FLASK_PORT,
|
|
427
|
+
debug=False,
|
|
428
|
+
threaded=True,
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
if __name__ == "__main__":
|
|
433
|
+
main()
|