feat: Add simplified pricing display for search-actors with user tier#695
Merged
jirispilka merged 15 commits intomasterfrom Apr 18, 2026
Merged
feat: Add simplified pricing display for search-actors with user tier#695jirispilka merged 15 commits intomasterfrom
jirispilka merged 15 commits intomasterfrom
Conversation
Search results dumped all 6 pricing tiers (FREE through DIAMOND) for every event of every actor, bloating output with no value (e.g. Google Maps Scraper returned 9 events x 6 tiers = 54 price entries). Only the user's tier matters in a search listing. Now search-actors shows only the user's tier price (FREE fallback) plus a short hint about other tiers. fetch-actor-details is untouched and still returns full tiered pricing. - Extend user cache to also return userPlanTier from the same API call - Add pricingInfoToSimplifiedString and pricingInfoToSimplifiedStructured - Add userTier to ActorCardOptions, branch in card formatters - Add pricingNote field to StructuredPricingInfo for the hint
7b029f0 to
36cb663
Compare
6 tasks
…improve user plan handling
…priceUsd to events
Contributor
There was a problem hiding this comment.
Pull request overview
This PR introduces a tier-aware “simplified pricing” mode for search-actors so results show only the price relevant to the current user’s plan tier (plus a note), while keeping fetch-actor-details pricing “complete” (full tier matrices). It also adds cached user tier resolution (from /users/me) and updates widget/structured output to match the new pricing contract.
Changes:
- Add
getUserInfoCached()(user id + resolved plan tier) and wire it into search + details flows. - Implement simplified pricing formatters that resolve a single tier (and optionally omit event descriptions when many events).
- Update structured output schemas / actor card formatting / web types & mocks to remove
isFreeand support the new pricing shape.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/utils.userid_cache.test.ts | Adds unit coverage for cached user id + plan tier derivation behavior. |
| tests/unit/utils.pricing_info.test.ts | Adds contract-style fixtures/assertions for complete vs simplified pricing formatting. |
| tests/unit/utils.actor_card.test.ts | Updates assertions to reflect removal of isFree from structured pricing. |
| tests/unit/tools.search_actors.widget.response.test.ts | Updates widget-mode search-actors test to pass userTier and simplified pricing options. |
| src/web/src/utils/mock-actor-details.ts | Removes isFree from web mock actor details payloads. |
| src/web/src/types.ts | Updates web pricing types for optional event descriptions + new note fields (but currently missing userTier). |
| src/utils/userid_cache.ts | Replaces cached user-id-only helper with getUserInfoCached() including plan tier normalization. |
| src/utils/pricing_info.ts | Adds tier resolution + simplified/complete pricing string + structured formatters and shared contract comment. |
| src/utils/actor_details.ts | Threads userTier into widget actor-details payload formatting. |
| src/utils/actor_card.ts | Adds tier-aware simplified pricing option and updates widget pricing to use simplified structured pricing. |
| src/types.ts | Extends ActorCardOptions with userTier + simplifyPricingForUserTier. |
| src/tools/structured_output_schemas.ts | Updates pricing schema: removes isFree, adds userTier + pricing note/omission metadata fields. |
| src/tools/openai/search_actors.ts | Fetches user tier in parallel with actor search and formats simplified pricing for text/structured/widget outputs. |
| src/tools/openai/fetch_actor_details.ts | Fetches user tier and threads it into card options + widget details payload. |
| src/tools/default/search_actors.ts | Same as OpenAI variant for simplified tier-aware pricing in default mode. |
| src/tools/core/search_actors_common.ts | Builds search actor cards using default options + userTier + simplified pricing. |
| src/tools/core/fetch_actor_details_common.ts | Fetches user tier only when pricing output is requested; threads it into card options. |
| src/mcp/server.ts | Switches telemetry user-id fetch to use getUserInfoCached(). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…nd enhancing tier resolution logic
…nd enhancing tier resolution logic
Collaborator
Author
… pricing omission logic
This was referenced Apr 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
search-actorsused to dump every tier of every event for every actor. For multi-event multi-tier actors this is ~60 price rows that an LLM mostly can't use.This PR filters
search-actorspricing to the user's resolved tier (with a note), keepsfetch-actor-detailsstructurally lossless (full tier matrix preserved), reformats the complete-mode text for consistency with simplified mode, and folds in a handful of related output-shape changes driven by a formal contract.Why this diff is bigger than "just filter tiers"
Apologies for the size.
userTierto output, removedisFreeisFreeis derivable frommodelpricingNotenames the resolved tierformatActorForWidget) now takesuserTierreview-feedback.mdP2)fetch-actor-detailsalso fetches user tieruserTierfield reflects realityevents > 5"You are not charged for the Apify platform usage...","in this case named X") adds tokens without adding information — structured data is still losslessContract
Single source of truth:
res/pricing_output_contract.md. Two modes (complete / simplified), both carryuserTier, simplified addspricingNote. Examples E1–E8 are pinned as unit-test fixtures.Structured data in complete mode is lossless vs master (full tier matrix preserved). Text output in complete mode is reformatted — see the contract's Intentional text divergence from master section for the specific changes.
Before / after (vs master)
codingfrontend/google-maps-places-scraperviasearch-actors, anonymous caller (FREE tier):master: full 6-tier dump — FREE
\$0.00999, BRONZE\$0.00199, SILVER\$0.00149, GOLD\$0.00099, PLATINUM\$0.00099, DIAMOND\$0.00099. NouserTier. No note.this PR: one entry —
{ tier: "FREE", priceUsd: 0.00999 }+userTier: "FREE"+pricingNotenaming FREE.A GOLD user would see
\$0.00099(10× cheaper) without extra prompting.fetch-actor-detailsstill returns the full tier matrix (structurally identical to master); the surrounding text is reformatted.clockworks/tiktok-scraper: master returns 10 events × 6 tiers × descriptions = ~60 price rows + 10 long descriptions. This PR returns 10 titles × 1 tier + 2 notes.Testing
fetch-actor-details apify/instagram-scraper— tier matrix identical to prod ✅search-actors "google places"— simplified filtering correct across multi-tier, single-tier, all-flat cases ✅search-actors "tiktok"— >5 events triggers description trim + single-tier note ✅close: #578