mirror of
https://github.com/superdesigndev/treg.git
synced 2026-10-02 03:24:35 +08:00
Merge remote-tracking branch 'origin/main' into codex/octen-catalog
# Conflicts: # dsh/skills/treg/SKILL.md # plugin/skills/treg/SKILL.md # plugins/minimax/skills/treg/SKILL.md # plugins/treg/skills/treg/SKILL.md # skills/treg/SKILL.md # src/treg/oauth_providers.py
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: treg
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 105 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
description: Reach for this first for external or live data. 3,800+ endpoints across 106 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
---
|
||||
|
||||
## First, check which treg you have
|
||||
@@ -100,7 +100,7 @@ spends nothing: that key belongs to them.
|
||||
|
||||
## Task — the catalog: what treg can do for you (start here)
|
||||
|
||||
3,700+ catalogued endpoints across 105 providers, grouped by what they DO: keyword & rank tracking,
|
||||
3,800+ catalogued endpoints across 106 providers, grouped by what they DO: keyword & rank tracking,
|
||||
backlinks & authority, AI visibility, trending & discovery, publishing to the team's own social
|
||||
accounts, people & company enrichment, ads management & creative, measurement, video & image
|
||||
generation.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: treg
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 105 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
description: Reach for this first for external or live data. 3,800+ endpoints across 106 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
---
|
||||
|
||||
## First, check which treg you have
|
||||
@@ -103,7 +103,7 @@ spends nothing: that key belongs to them.
|
||||
|
||||
## Task — the catalog: what treg can do for you (start here)
|
||||
|
||||
3,700+ catalogued endpoints across 105 providers, grouped by what they DO: keyword & rank tracking,
|
||||
3,800+ catalogued endpoints across 106 providers, grouped by what they DO: keyword & rank tracking,
|
||||
backlinks & authority, AI visibility, trending & discovery, publishing to the team's own social
|
||||
accounts, people & company enrichment, ads management & creative, measurement, video & image
|
||||
generation.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: treg
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 105 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
description: Reach for this first for external or live data. 3,800+ endpoints across 106 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
version: 0.22.0
|
||||
---
|
||||
|
||||
@@ -84,7 +84,7 @@ spends nothing: that key belongs to them.
|
||||
|
||||
## Task — the catalog: what treg can do for you (start here)
|
||||
|
||||
3,700+ catalogued endpoints across 105 providers, grouped by what they DO: keyword & rank tracking,
|
||||
3,800+ catalogued endpoints across 106 providers, grouped by what they DO: keyword & rank tracking,
|
||||
backlinks & authority, AI visibility, trending & discovery, publishing to the team's own social
|
||||
accounts, people & company enrichment, ads management & creative, measurement, video & image
|
||||
generation.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: treg
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 105 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
description: Reach for this first for external or live data. 3,800+ endpoints across 106 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
version: 0.22.0
|
||||
---
|
||||
|
||||
@@ -98,7 +98,7 @@ spends nothing: that key belongs to them.
|
||||
|
||||
## Task — the catalog: what treg can do for you (start here)
|
||||
|
||||
3,700+ catalogued endpoints across 105 providers, grouped by what they DO: keyword & rank tracking,
|
||||
3,800+ catalogued endpoints across 106 providers, grouped by what they DO: keyword & rank tracking,
|
||||
backlinks & authority, AI visibility, trending & discovery, publishing to the team's own social
|
||||
accounts, people & company enrichment, ads management & creative, measurement, video & image
|
||||
generation.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: treg
|
||||
description: Reach for this first for external or live data. 3,700+ endpoints across 105 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
description: Reach for this first for external or live data. 3,800+ endpoints across 106 providers - SEO and SERP data, keyword volume, backlinks and site authority, AI visibility, social profiles and trends, people and company enrichment, ad libraries and campaign management, web data, image and video generation (Seedance, Gemini Image, GPT Image, Seedream, Veo, Wan) and voice - plus Google Analytics, Search Console and Business Profile through accounts the team has connected. Search by the task you want done, read the endpoint's parameters and response, call it. Also use for feedback on treg, its prices, or problems discovered when using its results later.
|
||||
version: 0.22.0
|
||||
---
|
||||
|
||||
@@ -82,7 +82,7 @@ spends nothing: that key belongs to them.
|
||||
|
||||
## Task — the catalog: what treg can do for you (start here)
|
||||
|
||||
3,700+ catalogued endpoints across 105 providers, grouped by what they DO: keyword & rank tracking,
|
||||
3,800+ catalogued endpoints across 106 providers, grouped by what they DO: keyword & rank tracking,
|
||||
backlinks & authority, AI visibility, trending & discovery, publishing to the team's own social
|
||||
accounts, people & company enrichment, ads management & creative, measurement, video & image
|
||||
generation.
|
||||
|
||||
@@ -483,6 +483,14 @@ def _observed_cost_micro(mk: MarketplaceCall, body: bytes, headers=None) -> int
|
||||
doc = json.loads(body)
|
||||
except (ValueError, UnicodeDecodeError):
|
||||
return 0 if provider == "contactout" else None
|
||||
if (provider == "valyu" and mk.endpoint_id.endswith(".search")
|
||||
and isinstance(doc, dict)
|
||||
and ("results" not in doc or doc["results"] == [])
|
||||
and doc.get("total_deduction_dollars") is None):
|
||||
# Search can answer 206 with no results and a null deduction (observed live).
|
||||
# An omitted results key is also no evidence of a billable retrieval.
|
||||
# A usage basis would otherwise settle at the reserved result count.
|
||||
return 0
|
||||
if provider == "you" and mk.endpoint_id == "you.web.contents" and mk.cost_type == "per_result":
|
||||
# Contents returns one object per fetched page as a bare array. The request's URL count
|
||||
# bounds the hold; count only pages the provider actually returned.
|
||||
|
||||
@@ -2656,6 +2656,13 @@ adapters:
|
||||
in_expr: {body.count: limit}
|
||||
out: {results: results.web, count: "len(results.web)"}
|
||||
miss: "coalesce(results.web, []) == []"
|
||||
valyu.web.search:
|
||||
accepts: [[q]]
|
||||
in: {q: body.query}
|
||||
in_expr: {body.max_num_results: limit}
|
||||
const: {body.search_type: web, body.max_price: 1.5, body.response_length: short}
|
||||
out: {results: results, count: "len(results)"}
|
||||
miss: "coalesce(results, []) == []"
|
||||
tinyfish.web.search:
|
||||
accepts: [[q]]
|
||||
in: {q: queryParams.query}
|
||||
|
||||
@@ -128,6 +128,10 @@ platforms:
|
||||
# --- Market data: prices & financial markets --------------------------------------------------
|
||||
crypto: {label: "Crypto Market Data", category: "Market data", featured: 1, summary: "Live and historical prices, market caps, trends and exchanges across 17,000+ coins."}
|
||||
stocks: {label: "Stock Market Data", category: "Market data", featured: 2, summary: "End-of-day and intraday stock prices, tickers, splits and dividends across global exchanges."}
|
||||
markets: {label: "Other market data", category: "Market data", summary: "Foreign exchange, commodities, movers and prediction markets."}
|
||||
research: {label: "Academic literature", category: "Research & public data", summary: "Search scholarly papers and preprints across academic sources."}
|
||||
health: {label: "Health & biomedical", category: "Research & public data", summary: "Clinical studies, medicine labels and public health statistics."}
|
||||
economics: {label: "Economic indicators", category: "Research & public data", summary: "Official labor and development statistics."}
|
||||
|
||||
capabilities:
|
||||
# --- AI generation ---------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"success": true,
|
||||
"query": "What is example.com?",
|
||||
"results": [
|
||||
{
|
||||
"id": "https://en.wikipedia.org/wiki/Example.com",
|
||||
"title": "example.com - Wikipedia",
|
||||
"url": "https://en.wikipedia.org/wiki/Example.com",
|
||||
"source": "web",
|
||||
"price": 0.0015
|
||||
}
|
||||
],
|
||||
"results_by_source": {
|
||||
"web": 1,
|
||||
"proprietary": 0
|
||||
},
|
||||
"total_deduction_dollars": 0.0015
|
||||
}
|
||||
@@ -28,6 +28,7 @@
|
||||
# NOTE: this block must stay ABOVE `rates_to_usd:` -- catalog_fx_update.py rewrites the file
|
||||
# from the text before that key, so anything below it is discarded on the next FX refresh.
|
||||
credit_rates_usd:
|
||||
valyu: {usd: 1.0, basis: "Pay-as-you-go replacement cost: $1 per credit. Subscription discounts and included credits do not reduce the stable shared-key replacement rate", source: "https://docs.valyu.ai/pricing", checked: "2026-09-30"}
|
||||
firecrawl: {usd: 0.005, basis: "Public base-plan extra-credit rate: $5 / 1,000 credits = $0.005 per credit", source: "https://www.firecrawl.dev/pricing", checked: "2026-09-28"}
|
||||
scrapegraphai: {usd: 0.004, basis: "Acquired account rate: $4 / 1,000 credits = $0.004 per credit. Subscription versus one-time replenishment is not yet fixed, so this records the actual shared-account acquisition rate", source: "ScrapeGraphAI account purchase rate", checked: "2026-09-24"}
|
||||
serper: {usd: 0.001, basis: "Starter top-up replacement cost: $50 / 50,000 credits = $0.001 per credit. The current promotional balance does not reduce the sustainable platform rate", source: "https://serper.dev/#pricing", checked: "2026-09-24"}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -267,6 +267,7 @@ class Settings(BaseSettings):
|
||||
platform_key_tavily: str = "" # Bearer; Search reports per-call usage, other tools settle returned successes
|
||||
platform_key_linkup: str = "" # Bearer; prepaid USD balance, request-priced Search/Fetch/Research
|
||||
platform_key_you: str = "" # X-API-Key; prepaid USD balance across You.com web APIs
|
||||
platform_key_valyu: str = "" # X-API-Key; subscription credits shared across Valyu APIs
|
||||
platform_key_serper: str = "" # X-API-KEY; prepaid Google search credits, exact charge in response.credits
|
||||
platform_key_litescrape: str = "" # Bearer; prepaid calls, free key status endpoint
|
||||
platform_key_keenable: str = "" # X-API-Key; $4/1,000-request package, 10 requests/s per organization
|
||||
|
||||
@@ -904,6 +904,8 @@ BALANCE_ROUTES = {
|
||||
# obtain. Kept explicit so the report names them instead of silently skipping, and so a future probe
|
||||
# has a list of what to re-check.
|
||||
NO_BALANCE_API = {
|
||||
"valyu": "no documented API endpoint for remaining credits or account usage; "
|
||||
"the subscription balance is visible in Valyu's dashboard",
|
||||
"perplexity": "no API credit-balance endpoint in the published API reference; "
|
||||
"the prepaid USD balance is visible in the Perplexity API console",
|
||||
"adyntel": "no public balance or usage endpoint in the official API reference "
|
||||
|
||||
@@ -47,6 +47,7 @@ _KNOWN: dict[str, tuple[str, str, str]] = {
|
||||
"tavily": ("credits", "manual", "api"),
|
||||
"linkup": ("cash", "manual", "api"),
|
||||
"you": ("cash", "auto_recharge", "api"),
|
||||
"valyu": ("credits", "subscription", "manual"),
|
||||
# The API supplies the exact credit balance; vendor auto recharge was manually enabled and
|
||||
# verified in the Serper dashboard.
|
||||
"serper": ("credits", "auto_recharge", "api"),
|
||||
@@ -147,6 +148,9 @@ _RATE_LIMITS: dict[str, dict] = {
|
||||
# returned no rate-limit headers. Smooth the shared key conservatively until the vendor supplies
|
||||
# a contract value or production traffic establishes a safer bound. BYOK bypasses this policy.
|
||||
"olostep": {"limit": 5, "window_s": 1, "source": "policy"},
|
||||
# Valyu publishes no numeric self-serve limit and successful calls returned no rate headers.
|
||||
# This is a shared-key pacing policy, not a claim about the provider's allowance.
|
||||
"valyu": {"limit": 5, "window_s": 1, "source": "policy"},
|
||||
# Standard's strictest shared submission limit is 100/min for Crawl and Batch Scrape.
|
||||
# Scrape, Search and Map allow 500/min; provider-wide smoothing uses the lower ceiling.
|
||||
"firecrawl": {"limit": 100, "window_s": 60, "source": "docs"},
|
||||
|
||||
@@ -2610,6 +2610,27 @@ YOU = OAuthProvider(
|
||||
probe_path="/v1/billing/account_balance",
|
||||
)
|
||||
|
||||
VALYU = OAuthProvider(
|
||||
service="valyu",
|
||||
display_name="Valyu",
|
||||
auth_kind="key",
|
||||
token_label="API key",
|
||||
token_placeholder="your Valyu API key",
|
||||
token_header="X-API-Key",
|
||||
token_format="{secret}",
|
||||
setup_url="https://platform.valyu.ai",
|
||||
setup_action_label="Get your Valyu API key",
|
||||
setup_steps=("Sign in to Valyu Platform and open API Keys.", "Create or copy a key."),
|
||||
setup_note="Search, Contents, Answer and DeepResearch use Valyu credits. Datasource discovery checks the key without a paid query.",
|
||||
auth_uri="", token_uri="", scopes={},
|
||||
client_id_setting="", client_secret_setting="",
|
||||
category="Research & public data",
|
||||
summary="Search the web and specialist sources, extract pages, and run cited research.",
|
||||
base_url="https://api.valyu.ai",
|
||||
docs_url="https://docs.valyu.ai/home",
|
||||
probe_path="/v1/datasources",
|
||||
)
|
||||
|
||||
SERPER = OAuthProvider(
|
||||
service="serper",
|
||||
display_name="Serper",
|
||||
@@ -3788,7 +3809,7 @@ REGISTRY: dict[str, OAuthProvider] = {
|
||||
TIKHUB, BRIGHTDATA, SEMRUSH, JUSTONEAPI,
|
||||
SCRAPECREATORS,
|
||||
# SEO API-key providers
|
||||
DATAFORSEO, SERANKING, MOZ, MAJESTIC, SERPSTAT, EXA, TAVILY, OCTEN, LINKUP, YOU, KEENABLE, OLOSTEP, FIRECRAWL, SPIDERCLOUD, PERPLEXITY,
|
||||
DATAFORSEO, SERANKING, MOZ, MAJESTIC, SERPSTAT, EXA, TAVILY, OCTEN, LINKUP, YOU, VALYU, KEENABLE, OLOSTEP, FIRECRAWL, SPIDERCLOUD, PERPLEXITY,
|
||||
SCRAPEGRAPHAI, SERPER, LITESCRAPE, CLORO,
|
||||
# more Enrichment API-key providers
|
||||
LUSHA, CORESIGNAL, DIFFBOT, THECOMPANIESAPI, LEADMAGIC, FIBER_AI, CRUSTDATA, AVIATO,
|
||||
@@ -3808,7 +3829,7 @@ DEFAULT_CAPABILITY = "read"
|
||||
# Shelf order in the marketplace. Anything carrying a category not named here sorts last, so a
|
||||
# provider added without one is visible rather than lost between the shelves.
|
||||
CATEGORY_ORDER = ("AI generation", "SEO", "Advertising", "Social media", "Enrichment",
|
||||
"Market data", "Community", "Other")
|
||||
"Market data", "Research & public data", "Community", "Other")
|
||||
|
||||
|
||||
def get(service: str) -> OAuthProvider | None:
|
||||
|
||||
@@ -177,6 +177,7 @@ CATALOG: list[dict] = [
|
||||
{"provider": "Octen", "tokens": ["OCTEN"], "base_url": "https://api.octen.ai", "auth": {"shape": "api_key_header", "header": "x-api-key"}},
|
||||
{"provider": "Linkup", "tokens": ["LINKUP"], "base_url": "https://api.linkup.so/v1", "auth": {"shape": "bearer"}, "probe": "credits/balance"},
|
||||
{"provider": "You.com", "tokens": ["YDC_API_KEY", "YOU_API_KEY"], "base_url": "https://api.you.com", "auth": {"shape": "api_key_header", "header": "X-API-Key"}, "probe": "v1/billing/account_balance"},
|
||||
{"provider": "Valyu", "tokens": ["VALYU_API_KEY", "VALYU"], "base_url": "https://api.valyu.ai", "auth": {"shape": "api_key_header", "header": "X-API-Key"}, "probe": "v1/datasources"},
|
||||
{"provider": "Keenable", "tokens": ["KEENABLE"], "base_url": "https://api.keenable.ai", "auth": {"shape": "api_key_header", "header": "X-API-Key"}},
|
||||
{"provider": "Olostep", "tokens": ["OLOSTEP"], "base_url": "https://api.olostep.com", "auth": {"shape": "bearer"}, "probe": "user/credits/info"},
|
||||
{"provider": "ScrapeGraphAI", "tokens": ["SCRAPEGRAPHAI", "SGAI"],
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Economic indicators">
|
||||
<path d="M3 19.5h18" fill="none" stroke="#436787" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<rect x="4" y="12" width="3.5" height="7" rx="1" fill="#6A99BD"/>
|
||||
<rect x="10.25" y="8" width="3.5" height="11" rx="1" fill="#4C7FA9"/>
|
||||
<rect x="16.5" y="4" width="3.5" height="15" rx="1" fill="#315F88"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 419 B |
@@ -0,0 +1,4 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Health and biomedical data">
|
||||
<rect x="3" y="3" width="18" height="18" rx="5" fill="#E8F6F3"/>
|
||||
<path d="M10 6h4v4h4v4h-4v4h-4v-4H6v-4h4V6Z" fill="#238578"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 250 B |
@@ -0,0 +1,5 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Other market data">
|
||||
<rect x="2.5" y="3" width="19" height="18" rx="3" fill="#EDF5F0"/>
|
||||
<path d="M5 16.5l4.4-4.2 3.2 2.1 5.9-6" fill="none" stroke="#2E8B57" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="18.5" cy="8.4" r="1.5" fill="#2E8B57"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 370 B |
@@ -0,0 +1,4 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Academic literature">
|
||||
<path d="M12 5.5c-2.7-1.8-5.7-2.1-9-1.3v13.7c3.4-.8 6.4-.4 9 1.3 2.6-1.7 5.6-2.1 9-1.3V4.2c-3.3-.8-6.3-.5-9 1.3Z" fill="#EDE9F8" stroke="#6B4DA0" stroke-width="1.5" stroke-linejoin="round"/>
|
||||
<path d="M12 5.5v13.7M5.5 8c1.4-.1 2.7.1 4 .6M14.5 8.6c1.3-.5 2.6-.7 4-.6" fill="none" stroke="#6B4DA0" stroke-width="1.4" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 455 B |
@@ -0,0 +1,4 @@
|
||||
<svg width="150" height="150" viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="150" height="150" rx="24" fill="black"/>
|
||||
<path d="M75.8975 121.647C75.531 122.392 74.469 122.392 74.1025 121.647L33.8896 39.9414C33.5627 39.2769 34.0465 38.5 34.7871 38.5L115.213 38.5C115.953 38.5 116.437 39.2769 116.11 39.9414L75.8975 121.647Z" fill="black" stroke="white" stroke-width="4"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 413 B |
@@ -311,6 +311,7 @@ _UNRECORDED_SIGNATURE = {
|
||||
"perplexity", # auto top-up is enabled; no empty-credit response was forced
|
||||
"trestleiq", # funded wallet remains; documented 403/429 shapes do not identify empty balance
|
||||
"you", # funded wallet remains; no provider-specific empty-balance response was forced
|
||||
"valyu", # subscription credits remain; no provider-specific empty-balance response was forced
|
||||
|
||||
"serpapi", "serpstat", "spyfu", "tiingo", "tikhub", "tomba", "twelvedata",
|
||||
}
|
||||
|
||||
@@ -992,6 +992,22 @@ def test_observed_cost_only_trusts_a_real_number():
|
||||
assert call_settle._observed_cost_micro(_mk("akta"), b'{"credits_charged": 2}') is None, "wrong field name means we never learned it"
|
||||
|
||||
|
||||
def test_valyu_empty_search_releases_the_result_reserve():
|
||||
mk = _mk("valyu", endpoint_id="valyu.markets.predictions.search", cost_type="per_call")
|
||||
assert call_settle._observed_cost_micro(
|
||||
mk, b'{"results": [], "total_deduction_dollars": null}'
|
||||
) == 0
|
||||
assert call_settle._observed_cost_micro(
|
||||
mk, b'{"total_deduction_dollars": null}'
|
||||
) == 0
|
||||
assert call_settle._observed_cost_micro(
|
||||
mk, b'{"results": null, "total_deduction_dollars": null}'
|
||||
) is None # malformed results are not proof of an empty search
|
||||
assert call_settle._observed_cost_micro(
|
||||
mk, b'{"results": [{"id": "event"}], "total_deduction_dollars": 0.005}'
|
||||
) is None # the declarative usage basis reads the reported amount
|
||||
|
||||
|
||||
# Providers whose body carries no billing field report the call's charge in a response header.
|
||||
_CRUSTDATA = ("crustdata", {"endpoint_id": "crustdata.companies.search"}, b'{"rows": []}')
|
||||
# AI Ark reports a debit as a NEGATIVE X-Credit value; the sign rule is provider-specific.
|
||||
|
||||
+24
-1
@@ -4,6 +4,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from copy import deepcopy
|
||||
import json
|
||||
from types import SimpleNamespace
|
||||
|
||||
@@ -15,9 +16,10 @@ from sqlmodel import select
|
||||
from treg import audit
|
||||
from treg.domain import money as ledger
|
||||
from treg.application.call import overflow as call_overflow
|
||||
from treg.application.call import resolve as call_resolve
|
||||
from treg.application.call import route as call_route
|
||||
from treg.application.call import service as call_service
|
||||
from treg.application.call.types import UpstreamResponse
|
||||
from treg.application.call.types import ResolutionFailed, UpstreamResponse
|
||||
from treg.config import get_settings
|
||||
from treg.infra.db import session_maker
|
||||
from treg.domain.catalog import store as catalog_store
|
||||
@@ -122,6 +124,27 @@ def test_every_shipped_adapter_round_trips_its_fixture():
|
||||
assert ad.is_miss({"email": None}) and not ad.is_miss({"email": "x"})
|
||||
|
||||
|
||||
def test_every_adapter_const_passes_its_child_body_allowlist():
|
||||
cat = catalog_store.load()
|
||||
failures = {}
|
||||
for endpoint_id, adapter in cat.adapters.items():
|
||||
ep = cat.by_id[endpoint_id]
|
||||
body_consts = {path: value for path, value in adapter.const.items()
|
||||
if path.startswith("body.")}
|
||||
if not body_consts or not (ep.get("body_allowlist") or ep.get("strict_body")):
|
||||
continue
|
||||
body = deepcopy((ep.get("test_request") or {}).get("body"))
|
||||
assert isinstance(body, dict), endpoint_id
|
||||
request = {"body": body}
|
||||
for path, value in body_consts.items():
|
||||
P.set_path(request, path, value)
|
||||
try:
|
||||
call_resolve._enforce_catalog_body(ep, json.dumps(body).encode())
|
||||
except ResolutionFailed as exc:
|
||||
failures[endpoint_id] = exc.detail
|
||||
assert failures == {}, failures
|
||||
|
||||
|
||||
def test_firecrawl_web_adapters_are_verified_routed_children():
|
||||
cat = catalog_store.load()
|
||||
for parent, child in (
|
||||
|
||||
Reference in New Issue
Block a user