Integración con OpenCode
This commit is contained in:
parent
a7f8ddad08
commit
7228cf1b65
18
.claude/settings.json
Normal file
18
.claude/settings.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(python backfill_games_mayo.py)",
|
||||
"Bash(findstr /i \"GAMes Actualiz MetricasDiarias actualizado\" \"C:\\\\Users\\\\jmgom\\\\AppData\\\\Local\\\\Temp\\\\claude\\\\c--Users-jmgom-projects-leads-optimizer\\\\2e73bc62-0b35-4293-96e9-676bded17b5f\\\\tasks\\\\bf9cfc1r9.output\")",
|
||||
"Bash(findstr /i /c:\"actualiz\" \"C:\\\\Users\\\\jmgom\\\\AppData\\\\Local\\\\Temp\\\\claude\\\\c--Users-jmgom-projects-leads-optimizer\\\\2e73bc62-0b35-4293-96e9-676bded17b5f\\\\tasks\\\\bf9cfc1r9.output\")",
|
||||
"Bash(python -c ' *)",
|
||||
"Bash(git commit -m ' *)",
|
||||
"Bash(git push *)",
|
||||
"Bash(pkill -f \"streamlit run dashboard.py\")",
|
||||
"Skill(run)",
|
||||
"Skill(run:*)"
|
||||
],
|
||||
"additionalDirectories": [
|
||||
"C:\\Users\\jmgom\\projects\\meta-optimizer"
|
||||
]
|
||||
}
|
||||
}
|
||||
84
AGENTS.md
Normal file
84
AGENTS.md
Normal file
@ -0,0 +1,84 @@
|
||||
# Leads Optimizer — AGENTS.md
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
python run.py # main optimizer run
|
||||
python weekly_report.py # weekly strategic report
|
||||
streamlit run dashboard.py # Streamlit dashboard (port 15002)
|
||||
```
|
||||
|
||||
Python 3.12+. No build step, no linter, no test suite.
|
||||
|
||||
## Execution entry points
|
||||
|
||||
| File | Trigger | What it does |
|
||||
|------|---------|-------------|
|
||||
| `run.py` | daily.yml (00:00 UTC) or manual | Syncs Google Ads → Airtable, analyses campaigns, applies budget decisions, reports to Slack |
|
||||
| `weekly_report.py` | weekly.yml (Mon 07:00 UTC) or manual | Deeper week-over-week analysis via Anthropic, sends Slack |
|
||||
| `dashboard.py` | `streamlit run dashboard.py` | UI on port 15002, reads from Airtable directly |
|
||||
|
||||
## DRY_RUN mode
|
||||
|
||||
`config.py` has `DRY_RUN = True` by default. When `True`, decisions are printed but **no changes are applied to Google Ads**. Must be set to `False` to apply budget/pause changes. This is a module-level constant, not an env var.
|
||||
|
||||
## Required env vars (loaded via `python-dotenv` from `.env`)
|
||||
|
||||
All are mandatory except `SLACK_WEBHOOK_URL` (optional, has empty default):
|
||||
|
||||
- `AIRTABLE_TOKEN`, `AIRTABLE_BASE_ID`
|
||||
- `Google Ads`: `GOOGLE_ADS_DEVELOPER_TOKEN`, `GOOGLE_ADS_CLIENT_ID`, `GOOGLE_ADS_CLIENT_SECRET`, `GOOGLE_ADS_REFRESH_TOKEN`, `GOOGLE_ADS_LOGIN_CUSTOMER_ID` (digits only, no dashes)
|
||||
- `ANTHROPIC_API_KEY`
|
||||
- `SLACK_WEBHOOK_URL`
|
||||
|
||||
The `.github/workflows/` files pull these from GitHub Secrets. `run.sh` has **hardcoded secrets** — never commit changes to it.
|
||||
|
||||
## Architecture
|
||||
|
||||
Flat structure, no packages. Flow:
|
||||
|
||||
1. **Sync**: `airtable_client.py` + `google_ads_client.py` pull campaign catalog and monthly metrics from Google Ads, write to Airtable tables `Google Ads Campaigns`, `GACampaignMes`, `Leads Lake`, `MetricasDiarias`, `GAMes`.
|
||||
2. **Analyze**: `analyzer.py` computes per-campaign urgency (PAUSAR / SPRINT / ACELERAR / FRENAR / EN_RITMO).
|
||||
3. **Decide**: `agent.py` calls **Anthropic Claude (claude-sonnet-4-6)** per campaign to get JSON decision with action, budget multiplier, justification, and advice. Also produces portfolio-level analysis.
|
||||
4. **Apply**: `optimizer.py` mutates Google Ads campaigns (budget changes, pause/unpause) — only if `DRY_RUN = False`.
|
||||
5. **Report**: `slack_reporter.py` sends formatted summary to Slack via webhook.
|
||||
|
||||
## Campaign naming conventions
|
||||
|
||||
Campaigns follow naming patterns that drive logic:
|
||||
|
||||
- `fco_search_<N>` — Search campaigns for formation courses
|
||||
- `fco_pmx_<N>` — PMX (Performance Max) campaigns
|
||||
- `fco_leadform_<N>` — Lead form campaigns (leads captured inside Google, never reach Airtable)
|
||||
|
||||
When a course has both Search and PMX campaigns (`_search_` + `_pmx_` with same `<N>`), Search conversions reflow to PMX. When PMX has a `_leadform` companion, leadform conversions are summed into the PMX campaign's `leads_grupo`. If a course has multiple PMX campaigns (excluding leadform), paths 4/5 are disabled to avoid double counting.
|
||||
|
||||
## Month-boundary metric handling
|
||||
|
||||
`run.py` has special logic (lines ~400-432) for when yesterday belongs to a different calendar month. It merges into the **previous month's** `GACampaignMes` record instead of overwriting the new month's (avoids a known bug that erased June history). Any edits to the metrics-writing section must preserve this redirect.
|
||||
|
||||
## Airtable tables
|
||||
|
||||
- `Google Ads Campaigns` — master campaign catalog (Curso, GoogleCampaignID, PPL, CapTotalMes, CPAMaximo, Activa)
|
||||
- `Leads Lake` — individual lead records (GoogleCampaignID, FechaEntrada)
|
||||
- `GACampaignMes` — per-campaign monthly snapshot; updated each run with leads, advice, criticidad, metricas_diarias
|
||||
- `MetricasDiarias` — JSON field with per-day {coste, ingreso, margen, leads, leads_lake}
|
||||
- `GAMes` — aggregated daily totals for all fco_ campaigns + monthly totals
|
||||
|
||||
## Backfill and migration scripts
|
||||
|
||||
Scripts prefixed `backfill_*` and `migrate_*` are one-off data scripts. Do not call them from normal flow; they are only for historical data repairs.
|
||||
|
||||
## CI/CD
|
||||
|
||||
- `daily.yml` — runs `python run.py` at 00:00 UTC (2 AM CEST / 1 AM CET)
|
||||
- `weekly.yml` — runs `python weekly_report.py` Monday at 07:00 UTC (9 AM CEST)
|
||||
- Both use `ubuntu-latest` + Python 3.12 + secrets from GitHub
|
||||
- Logs uploaded as artifacts (30-day retention)
|
||||
|
||||
## Gotchas
|
||||
|
||||
- `run.py` wraps `sys.stdout` with a custom `Tee` class that writes to both console and `logs/<timestamp>.log`. Do not remove this.
|
||||
- The Anthropic model is hardcoded to `claude-sonnet-4-6` in `agent.py`. If the model changes, update all three calls (`decide`, `portfolio_daily_analysis`, `weekly_strategic_analysis`).
|
||||
- `run.sh` contains real API secrets — it should NOT be committed. Use `.env` + `python run.py` instead.
|
||||
Loading…
x
Reference in New Issue
Block a user