Skip to content

fix(mcp): real quota display (% + $), billing-aware unlimited, quota-not-credits enrichment#152

Merged
ArtyETH06 merged 10 commits into
mainfrom
ArtyETH06/fix-quota-understanding-in-the-mcp
Jul 8, 2026
Merged

fix(mcp): real quota display (% + $), billing-aware unlimited, quota-not-credits enrichment#152
ArtyETH06 merged 10 commits into
mainfrom
ArtyETH06/fix-quota-understanding-in-the-mcp

Conversation

@ArtyETH06

@ArtyETH06 ArtyETH06 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What & why

The MCP talked in raw "credits" for quota, and a freemium user with quota left was wrongly told they couldn't enrich. This unifies the full fix for #3865 (folds in the enrichment work from the former #153).

1. Quota renders like the frontend. leadbay_account_status shows a per-window % used + $ spend gauge (daily/weekly/monthly, from quota_status spend[]), with a per-resource breakdown fallback when the plan has no spend cap. Included on any account question (incl. "what account am I connected to?"); silent only when unreadable, unlimited, or null.

2. Billing-aware unlimited. @leadbay.ai is unlimited only when billing is disabled (seat sentinel 100000, or billing absent). Metered freemium/paid @leadbay.ai is treated as a real user — real gauge, real gate.

3. Enrichment is gated by quota, not credits. Removed the buggy client-side ai_credits <= 0 refusal (ai_credits is credits CONSUMED, starts at 0 — it falsely blocked freemium accounts). The backend 429 is the real gate. Reframed all enrich prompts + the runtime elicitation copy from "credits" to quota (email + phone reveals consume quota). "Enrich" with no channel → the agent asks email-only vs email+phone via ask_user_input_v0.

4. Refreshed quota after a paid action. After a completed enrichment or a confirmed top-up, the agent shows the refreshed per-window gauge.

Changes

  • rendering/quota-windows.md (new) + account-status.md.tmpl — the gauge render.
  • _credits-helpers.ts billing-aware isUnlimitedAccount; types.tsbilling.seats, QuotaResourceUsage.max_units, topup, nullable plan/org.
  • tools/enrich-contacts.ts — dropped the credit gate; advisory read only.
  • Enrich templates + enrich-titles.ts runtime elicitation — quota-not-credits + ask-about-phone.
  • server-instructions/quota-topup.md + bulk-enrich-status.md.tmpl — show-quota-after-spend.
  • Tests: new account-status-quota-render.test.ts, unlimited-billing-aware.test.ts, enrich-contacts-quota-gate.test.ts. Superseded the obsolete credit-gate contract by removing unlimited-account.test.ts + enrich-contacts-unlimited.test.ts and rewriting enrich-contacts.test.ts (delete+rewrite, per repo owner's explicit direction — the obsolete assertions tested the exact bug being fixed; all still-valid coverage carried over).

Verification

  • pnpm -r build && pnpm -r test && pnpm -r typecheck — green (core 539, mcp 525, promptforge 16, components 47).
  • Live-probed the real API + Claude Desktop: metered @leadbay.ai freemium now returns unlimited_credits: false + populated spend[]; the gauge renders; enrichment no longer false-refuses.

No eval run (author-run; prompt-behaviour change). WORKFLOW 30 (silent-on-unreadable-quota) stays green.

Closes https://github.com/leadbay/product/issues/3865

…imited billing-aware

leadbay_account_status described quota in raw 'credits'. Now it mirrors the
web app: a % used + $ spend gauge per daily/weekly/monthly window (from
quota_status spend[]), with a per-resource breakdown fallback when no spend
cap exists. Quota is included on any account-status question when readable.

Also fixes the unlimited-account rule: an @leadbay.ai account is unlimited
ONLY when billing is disabled (backend seat sentinel 100000, or billing
absent). @leadbay.ai with billing ENABLED (metered freemium/paid) is now
treated as a real user — real quota gauge, real credit gate.

Co-Authored-By: Claude <noreply@anthropic.com>
@ArtyETH06 ArtyETH06 self-assigned this Jul 7, 2026
github-actions Bot and others added 2 commits July 7, 2026 15:16
After a quota-consuming action completes (bulk enrich all_done, enrich_contacts)
or a confirmed top-up, the agent now calls leadbay_account_status and shows the
per-window %/$ quota gauge — the canonical surface — instead of only a bare
credits line. Skipped for unlimited accounts, unreadable quota, or no billing.

Co-Authored-By: Claude <noreply@anthropic.com>
…channel

The client pre-refused enrichment when billing.ai_credits <= 0, but ai_credits
is credits CONSUMED (an accumulator starting at 0) — so freemium/fresh accounts
with quota still available were falsely blocked ('No enrichment credits
remaining'). Removed the client-side gate; the backend 429 is the real quota
gate. Reframed enrich prompts to talk QUOTA (email + phone reveals consume
quota), dropping the confusing 'credits' framing and the fabricated 'You have N
credits' line. When the user asks to enrich without naming a channel, the agent
now asks via ask_user_input_v0 whether to add phone (email is the default).

Superseded the obsolete credit-gate tests (enrich-contacts.test.ts rewritten;
enrich-contacts-unlimited.test.ts → enrich-contacts-quota-gate.test.ts).

Co-Authored-By: Claude <noreply@anthropic.com>
github-actions Bot and others added 2 commits July 7, 2026 16:17
The runtime elicitation prompt (shown directly by the host on an
elicitation-capable path) said 'This spends credits (balance: N)' — bypassing
the template reframe. Rewrote it to talk quota (email/phone reveals consume
quota) and reframed the credits_remaining output-schema description to
advisory-only (never a spend gate). Addresses Codex review on #152.

Co-Authored-By: Claude <noreply@anthropic.com>
…quota-understanding-in-the-mcp

# Conflicts:
#	packages/core/src/tool-descriptions.generated.ts
#	packages/promptforge/tool-descriptions/composite/bulk-enrich-status.md.tmpl
@ArtyETH06 ArtyETH06 changed the title fix(mcp): show real quota (% + $ per window), billing-aware unlimited fix(mcp): real quota display (% + $), billing-aware unlimited, quota-not-credits enrichment Jul 7, 2026
github-actions Bot and others added 2 commits July 7, 2026 16:35
…NS_EXTRA_REFILL

The new quota guidance preferred quota.user and referred to the resource as
lowercase lens_extra_refill. But leadbay_extend_lens pre-checks are ORG-scoped
(extend-lens.ts reads quota.org.resources) and match the uppercase
LENS_EXTRA_REFILL. Carved out the pre-check: user preference stays for the
display gauge only; the LENS_EXTRA_REFILL pre-check reads quota.org.resources[]
and matches case-insensitively (both casings). Addresses Codex review on #152.

Co-Authored-By: Claude <noreply@anthropic.com>
…untime lookup

readExtraRefillQuota() matched the resource type with exact-case
=== "LENS_EXTRA_REFILL", but the live quota API emits lowercase
lens_extra_refill — so a 429 from leadbay_extend_lens nulled out used_today /
resets_at even though the backend supplied the row. Now normalizes case
(toUpperCase compare), matching the lowercase shape this PR documents as valid.
New test file covers the lowercase + mixed-case rows. Addresses Codex review on #152.

Co-Authored-By: Claude <noreply@anthropic.com>
@ArtyETH06 ArtyETH06 marked this pull request as ready for review July 8, 2026 00:00

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e4446b4486

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/promptforge/tool-descriptions/granular/enrich-contacts.md.tmpl Outdated
Comment thread packages/core/test/unit/tools/enrich-contacts.test.ts Outdated
Comment thread packages/promptforge/snippets/server-instructions/quota-topup.md Outdated
Comment thread packages/core/src/composite/_credits-helpers.ts Outdated
1. Preserve unlimited when seats absent: @leadbay.ai + billing present but no
   seats is now treated as unknown/legacy-disabled (unlimited), not metered —
   fixes a product#3851 regression for the pre-3865 internal shape.
2. Granular enrich: credits_remaining is advisory/non-displayable — never print
   _(N credits remaining)_ (0 falsely reads as out-of-credits on quota-gated).
3. Post-spend refresh: leadbay_enrich_contacts only LAUNCHES async work, so
   defer the quota refresh to bulk all_done / get_contacts enrichment.done —
   not immediately after the granular launch.
4. Keep tests in new files: restored enrich-contacts.test.ts to main minus the
   obsolete throw test; new quota-gate coverage lives in the new file.

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0e87a0e3ea

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/promptforge/tool-descriptions/composite/bulk-enrich-status.md.tmpl Outdated
Comment thread packages/core/src/composite/enrich-titles.ts Outdated
Comment thread packages/promptforge/snippets/rendering/quota-windows.md Outdated
1. bulk-enrich-status: credits_remaining is advisory/non-displayable — stop
   allowing _(N credits remaining)_ (a consumed counter reads 0 on a
   quota-backed account, falsely 'out of credits'). account_status gauge is the
   only quota surface.
2. enrich-titles no-channel elicitation now offers a phone opt-in (include_phone
   toggle) instead of silently confirming email-only, honoring the promised
   'email vs email + phone' choice. New test file covers it.
3. lens-refill pre-check falls back to quota.user.resources[] when quota.org is
   absent (non-admin callers only get the user group) — else the row is
   invisible and the write burns the 429 the pre-check exists to avoid. Applied
   in the snippet, template, account-status schema, and extend-lens runtime.

Co-Authored-By: Claude <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5b8adb6406

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/promptforge/prompts/leadbay_build_campaign.md.tmpl
Comment thread packages/core/src/tools/get-quota.ts
Comment thread packages/promptforge/tool-descriptions/composite/account-status.md.tmpl Outdated
1. bulk-enrich-status OUTPUT SCHEMA: credits_remaining reframed advisory/
   non-displayable (the template was fixed earlier; the schema still called it a
   balance — MCP clients see both).
2. Direct extend-lens prompts (extend-lens.md.tmpl + leadbay_extend_my_lens):
   lens-refill pre-check now org-first then user-fallback + case-insensitive,
   matching the account-status guidance.
3. WORKFLOWS.md 34 & 42: drop the 'surface credits_remaining' requirement —
   surface enrichable_contacts only; enrichment consumes quota, credits not
   displayed. Keeps the normative contract aligned with the prompt change.
4. get-quota template/description: prefer user group (org admin-only), describe
   spend[] %/$ gauge + resources[] + topup, case-insensitive types, no 'credits'.
5. account-status rendering_hint: prefer quota.user, fall back to quota.org when
   user absent (admins/legacy org-only shapes keep their display).

Co-Authored-By: Claude <noreply@anthropic.com>
@ArtyETH06 ArtyETH06 merged commit c82a873 into main Jul 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant