adloop 0.19.1__tar.gz → 0.19.2__tar.gz
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.
- {adloop-0.19.1 → adloop-0.19.2}/PKG-INFO +1 -1
- {adloop-0.19.1 → adloop-0.19.2}/pyproject.toml +1 -1
- {adloop-0.19.1 → adloop-0.19.2}/pyproject.toml.orig +1 -1
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/write.py +21 -1
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/server.py +15 -10
- {adloop-0.19.1 → adloop-0.19.2}/README.md +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/__init__.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/__main__.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/_mcp_patches.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/__init__.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/ai_max.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/brands.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/client.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/conversion_actions.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/currency.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/custom_conversion_goals.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/enums.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/forecast.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/gaql.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/image_fetch.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/pmax.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/read.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ads/validate_only.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/auth.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/cli.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/config.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/crossref.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/diagnostics.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ga4/__init__.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ga4/client.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ga4/reports.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ga4/tracking.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/ga4/write.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/gsc/__init__.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/gsc/client.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/gsc/reports.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/gtm/__init__.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/gtm/client.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/gtm/read.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/merchant/__init__.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/merchant/client.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/merchant/read.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/pagespeed.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/reddit/__init__.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/reddit/auth.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/reddit/client.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/reddit/read.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/reddit/schedule.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/reddit/write.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/rules/__init__.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/rules/adloop.md +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/rules/commands/analyze-performance.md +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/rules/commands/budget-plan.md +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/rules/commands/create-ad.md +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/rules/commands/create-campaign.md +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/rules/commands/diagnose-tracking.md +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/rules/commands/optimize-campaign.md +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/rules_install.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/runtime.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/safety/__init__.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/safety/audit.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/safety/guards.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/safety/preview.py +0 -0
- {adloop-0.19.1 → adloop-0.19.2}/src/adloop/tracking.py +0 -0
|
@@ -2780,7 +2780,27 @@ def confirm_and_apply(
|
|
|
2780
2780
|
"objects an earlier step would create, so Google could "
|
|
2781
2781
|
"only validate the step(s) before them."
|
|
2782
2782
|
)
|
|
2783
|
-
|
|
2783
|
+
from adloop.runtime import deployment_mode as _deployment_mode
|
|
2784
|
+
|
|
2785
|
+
if forced_by_config and _deployment_mode() == "server":
|
|
2786
|
+
# Hosted: the flag is the workspace's live-changes setting,
|
|
2787
|
+
# switched in the dashboard. There is no config file to edit
|
|
2788
|
+
# and no server for the user to restart.
|
|
2789
|
+
response["dry_run_forced_by"] = "config.safety.require_dry_run"
|
|
2790
|
+
response["remediation"] = (
|
|
2791
|
+
"Live changes are switched off for this workspace (or for "
|
|
2792
|
+
"this client). The workspace owner can switch them on in "
|
|
2793
|
+
"the AdLoop Cloud dashboard under Settings → Safety. Passing "
|
|
2794
|
+
"dry_run=false on this tool will keep being overridden until "
|
|
2795
|
+
"then."
|
|
2796
|
+
)
|
|
2797
|
+
response["message"] = (
|
|
2798
|
+
"dry_run=false was IGNORED because live changes are switched "
|
|
2799
|
+
"off for this workspace. No changes were made. Retrying this "
|
|
2800
|
+
"tool with dry_run=false will not succeed until live changes "
|
|
2801
|
+
"are switched on in the dashboard."
|
|
2802
|
+
)
|
|
2803
|
+
elif forced_by_config:
|
|
2784
2804
|
# The caller passed dry_run=false but safety.require_dry_run
|
|
2785
2805
|
# forced it back on. Tell them exactly why and how to unlock
|
|
2786
2806
|
# real writes — without this, agents (e.g. Claude Code) retry
|
|
@@ -310,13 +310,20 @@ def _structured_error(fn_name: str, exc: Exception) -> dict:
|
|
|
310
310
|
}
|
|
311
311
|
|
|
312
312
|
if "deleted_client" in err_lower or "invalid_client" in err_lower:
|
|
313
|
+
from adloop.runtime import deployment_mode
|
|
314
|
+
|
|
313
315
|
return {
|
|
314
316
|
"error": (
|
|
315
317
|
"Authentication failed — the OAuth client behind your stored "
|
|
316
318
|
"credentials no longer exists or is invalid."
|
|
317
319
|
),
|
|
320
|
+
# On a hosted server the user never sees an OAuth client: the
|
|
321
|
+
# fix is reconnecting, and pointing at a product would be an ad.
|
|
318
322
|
"hint": (
|
|
319
|
-
"
|
|
323
|
+
"Reconnect Google in your AdLoop Cloud dashboard "
|
|
324
|
+
"(Settings → Google), then retry."
|
|
325
|
+
if deployment_mode() == "server"
|
|
326
|
+
else "If you set up AdLoop before v0.10 with its bundled "
|
|
320
327
|
"credentials: that shared Google Cloud project has been "
|
|
321
328
|
"retired. Fastest fix: AdLoop Cloud (https://getadloop.com) — "
|
|
322
329
|
"connect Google in two clicks, no Google Cloud project "
|
|
@@ -652,7 +659,7 @@ def run_gsc_report(
|
|
|
652
659
|
finding keyword opportunities, and cross-referencing with GA4 and Ads data.
|
|
653
660
|
|
|
654
661
|
site_url: the GSC property URL (e.g. "https://example.com/" or
|
|
655
|
-
"sc-domain:example.com"). Defaults to
|
|
662
|
+
"sc-domain:example.com"). Defaults to the configured Search Console site.
|
|
656
663
|
dimensions: one or more of ["query", "page", "country", "device", "date"].
|
|
657
664
|
Defaults to ["query"].
|
|
658
665
|
date_range_start / date_range_end: ISO dates (YYYY-MM-DD) or relative
|
|
@@ -2633,14 +2640,12 @@ def confirm_and_apply(
|
|
|
2633
2640
|
to make real changes to the ad account (Google Ads or Reddit Ads — the
|
|
2634
2641
|
plan knows which platform it targets).
|
|
2635
2642
|
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
user edits the config file, sets 'require_dry_run: false', and restarts
|
|
2643
|
-
the AdLoop MCP server.
|
|
2643
|
+
Forced dry runs: when real changes are switched off (live changes off
|
|
2644
|
+
for the workspace in AdLoop Cloud, or safety.require_dry_run in a
|
|
2645
|
+
self-hosted config), dry_run=false is IGNORED and the result is still
|
|
2646
|
+
DRY_RUN_SUCCESS, with 'dry_run_forced_by' and 'remediation' fields.
|
|
2647
|
+
Pass the remediation on to the user and stop retrying: calling again
|
|
2648
|
+
with dry_run=false changes nothing until that setting is changed.
|
|
2644
2649
|
|
|
2645
2650
|
Two-phase apply: if 'safety.two_phase_apply: true' is set (always on
|
|
2646
2651
|
for AdLoop Cloud tenants), dry_run=false is REFUSED with status
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|