adloop 0.5.0__tar.gz → 0.5.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.
Files changed (28) hide show
  1. {adloop-0.5.0 → adloop-0.5.2}/PKG-INFO +2 -1
  2. {adloop-0.5.0 → adloop-0.5.2}/README.md +1 -0
  3. {adloop-0.5.0 → adloop-0.5.2}/pyproject.toml +1 -1
  4. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/__init__.py +1 -1
  5. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/ads/write.py +21 -14
  6. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/__main__.py +0 -0
  7. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/ads/__init__.py +0 -0
  8. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/ads/client.py +0 -0
  9. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/ads/currency.py +0 -0
  10. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/ads/forecast.py +0 -0
  11. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/ads/gaql.py +0 -0
  12. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/ads/pmax.py +0 -0
  13. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/ads/read.py +0 -0
  14. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/auth.py +0 -0
  15. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/bundled_credentials.json +0 -0
  16. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/cli.py +0 -0
  17. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/config.py +0 -0
  18. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/crossref.py +0 -0
  19. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/ga4/__init__.py +0 -0
  20. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/ga4/client.py +0 -0
  21. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/ga4/reports.py +0 -0
  22. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/ga4/tracking.py +0 -0
  23. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/safety/__init__.py +0 -0
  24. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/safety/audit.py +0 -0
  25. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/safety/guards.py +0 -0
  26. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/safety/preview.py +0 -0
  27. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/server.py +0 -0
  28. {adloop-0.5.0 → adloop-0.5.2}/src/adloop/tracking.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: adloop
3
- Version: 0.5.0
3
+ Version: 0.5.2
4
4
  Summary: Stop switching between Google Ads, GA4, and your code editor to figure out why conversions dropped.
5
5
  Keywords: mcp,google-ads,google-analytics,ga4,cursor,marketing
6
6
  Author: Daniel Klose
@@ -392,6 +392,7 @@ What's been shipped and what's next:
392
392
  - ~~PyPI package~~ ✓ — `pip install adloop`
393
393
  - ~~Bundled OAuth credentials~~ ✓ — no Google Cloud project required, auto-discovery of GA4/Ads accounts
394
394
  - ~~Headless server support~~ ✓ — manual URL copy-paste flow for servers without a browser
395
+ - ~~Behavioral eval suites~~ ✓ — 28 prompt-and-expectation tests covering read, write, tracking, and planning workflows
395
396
  - **Community launch** — HN, Indie Hackers, r/cursor, Twitter
396
397
  - **Video walkthrough**
397
398
 
@@ -368,6 +368,7 @@ What's been shipped and what's next:
368
368
  - ~~PyPI package~~ ✓ — `pip install adloop`
369
369
  - ~~Bundled OAuth credentials~~ ✓ — no Google Cloud project required, auto-discovery of GA4/Ads accounts
370
370
  - ~~Headless server support~~ ✓ — manual URL copy-paste flow for servers without a browser
371
+ - ~~Behavioral eval suites~~ ✓ — 28 prompt-and-expectation tests covering read, write, tracking, and planning workflows
371
372
  - **Community launch** — HN, Indie Hackers, r/cursor, Twitter
372
373
  - **Video walkthrough**
373
374
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "adloop"
3
- version = "0.5.0"
3
+ version = "0.5.2"
4
4
  description = "Stop switching between Google Ads, GA4, and your code editor to figure out why conversions dropped."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -2,7 +2,7 @@
2
2
 
3
3
  import sys
4
4
 
5
- __version__ = "0.5.0"
5
+ __version__ = "0.5.2"
6
6
 
7
7
 
8
8
  def main() -> None:
@@ -2525,22 +2525,29 @@ def _apply_create_negative_keyword_list(
2525
2525
  ) -> dict:
2526
2526
  """Create a shared negative keyword list and attach it to a campaign.
2527
2527
 
2528
- Executes three sequential API calls. If step 2 or 3 fails, the result
2529
- includes partial_failure info with the SharedSet resource name so the
2530
- caller can clean up or retry the remaining steps.
2528
+ Executes three sequential API calls. If any step fails, the result
2529
+ includes partial_failure info with the SharedSet resource name (if
2530
+ created) so the caller can clean up or retry the remaining steps.
2531
2531
  """
2532
- shared_set_resource = None
2533
-
2534
2532
  # 1. Create the SharedSet
2535
- shared_set_service = client.get_service("SharedSetService")
2536
- ss_op = client.get_type("SharedSetOperation")
2537
- shared_set = ss_op.create
2538
- shared_set.name = changes["list_name"]
2539
- shared_set.type_ = client.enums.SharedSetTypeEnum.NEGATIVE_KEYWORDS
2540
- ss_response = shared_set_service.mutate_shared_sets(
2541
- customer_id=cid, operations=[ss_op]
2542
- )
2543
- shared_set_resource = ss_response.results[0].resource_name
2533
+ try:
2534
+ shared_set_service = client.get_service("SharedSetService")
2535
+ ss_op = client.get_type("SharedSetOperation")
2536
+ shared_set = ss_op.create
2537
+ shared_set.name = changes["list_name"]
2538
+ shared_set.type_ = client.enums.SharedSetTypeEnum.NEGATIVE_KEYWORDS
2539
+ ss_response = shared_set_service.mutate_shared_sets(
2540
+ customer_id=cid, operations=[ss_op]
2541
+ )
2542
+ shared_set_resource = ss_response.results[0].resource_name
2543
+ except Exception as exc:
2544
+ return {
2545
+ "partial_failure": True,
2546
+ "shared_set_resource": None,
2547
+ "completed_steps": [],
2548
+ "failed_step": "create_shared_set",
2549
+ "error": _extract_error_message(exc),
2550
+ }
2544
2551
 
2545
2552
  # 2. Add keywords to the list
2546
2553
  try:
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