feat(sdk): MeterClient batching, retry, preserved idempotency (1.2.1) - #32
Open
Z333Q wants to merge 3 commits into
Open
feat(sdk): MeterClient batching, retry, preserved idempotency (1.2.1)#32Z333Q wants to merge 3 commits into
Z333Q wants to merge 3 commits into
Conversation
… (1.2.1)
Bumps @p402/sdk to 1.2.1. Adds three capabilities to MeterClient:
- recordEventsBatch(events) targets POST /api/v2/meter/events/batch.
The router landed the endpoint in the same slice; per-event failures
surface individually so callers can retry only the ids that need it.
- Optional buffered mode via constructor `batch: { maxEvents, maxLatencyMs }`.
enqueueEvent(event) auto-flushes on either bound; flush() force-flushes
pending. Without a batch config the client behaves exactly as before.
- fetchWithRetry wraps every meter HTTP call. Exponential backoff with
full jitter on network errors and 5xx. Defaults 3 / 200ms / 5000ms,
constructor-overridable. 429 is not retried — surfaces immediately as
RATE_LIMITED so the caller can apply its own backoff.
Per-event request_ids are preserved verbatim across retries. The router
UPSERTs on (tenant_id, request_id), so a duplicate submission produces
the same event_id — safe to retry aggressively without deduping on the
client side.
The content-key guard (scanForForbiddenContent) now fires on every event
path — single, batch, and enqueue — before any bytes leave the process.
New meter tests (13) cover retry, batch, and buffered mode. Existing 17
pass unchanged. Typecheck clean; smoke passes. This matches the tarball
already published to npm as 1.2.1.
README updated with the batch endpoint, buffered-mode + retry section,
and an OutcomesClient reference.
Documents the four meter endpoints and the SDK 1.2.1 surface in the
places that already document routing / sessions / payments:
- docs/getting-started.md: new step 5 for Path B metering with single +
batch snippets and pointer to the buffered example.
- skills/p402/references/api-reference.md: new "Meter Events" section
covering all four endpoints (POST single, POST batch, GET list, GET
detail), privacy contract, idempotency posture, and MeterClient
usage. Table of contents renumbered.
- skills/p402/SKILL.md: adds the three meter endpoints to the API
Quick Reference table and a Pattern 6 ("Meter-Only Path") to the
integration patterns list.
- examples/05-meter-events/: new example. index.ts demonstrates single
event, batch with a deliberate duplicate to prove UPSERT idempotency,
buffered enqueueEvent + flush via direct MeterClient construction,
and the client-side content-key guard rejecting a prompt-bearing
event before any network call. README documents the privacy
contract, forbidden keys, and retry policy.
No changes to openapi.yaml — the meter endpoints are not currently in
that file at all (pre-existing gap, out of scope for this PR).
Adds pricing-model alignment across the CLI and the p402 skill. CLI - New `p402 plan` command prints the P402 plan ladder (Sandbox / Build / Growth / Scale / Enterprise) matching the router's lib/pricing/rate-card.ts v2 (effective 2026-06-21). Includes bridge offers (AI Spend Audit, Proof Sprint, Paid Pilot, Regulated Pilot). - `--json` emits the rate card as machine-readable JSON. - `--current` will call a Bearer-authed router endpoint returning the tenant's plan and month-to-date usage once the router exposes one. Until then it prints a clear pointer to the dashboard rather than lying about what the CLI can see. - README updated. Skill - SKILL.md gains a "Which Tier" section under Integration Patterns with the full ladder and bridge offers, explicitly citing the rate card as the source of truth. - references/api-reference.md gains a "Plans and Metering" section covering the ladder, the definition of a metered event, alert thresholds, the legacy plan-vocabulary bridge in plan-compat.ts, bridge offers, and the current-tier lookup gap. Table of contents renumbered. Alignment posture - Nothing in the SDK / CLI / skill was previously stale or misaligned; the surfaces were just silent on the ladder. This commit makes the pricing model discoverable from a terminal (`p402 plan`) and from the skill (SKILL.md tier table + api-reference plans section), without changing any runtime behavior.
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
Syncs the source of
@p402/sdk@1.2.1— already published to npm — with the public repo. Registry and source had drifted; this closes the gap.Three additions to
MeterClient:recordEventsBatch(events)targets the router's newPOST /api/v2/meter/events/batch. Per-event failures land inresultswithok: falseso callers can retry only the events that need it.batch: { maxEvents, maxLatencyMs }, plusenqueueEvent(event)andflush(). Without abatchconfig the client behaves as before.fetchWithRetrywraps every meter HTTP call. Exponential backoff with full jitter on network errors and 5xx. Defaults3 / 200ms / 5000ms, all constructor-overridable.429is not retried and surfaces immediately asRATE_LIMITED.Per-event
request_ids are preserved verbatim across retries. The router UPSERTs on(tenant_id, request_id), so duplicate submissions produce the sameevent_id— safe to retry aggressively.Content-key guard runs on every event path (single, batch, enqueue) before any bytes leave the process.
README updated: batch endpoint, buffered-mode + retry section (using
MeterClientdirectly),OutcomesClientreference.What's not in this PR
P402Client/P402Configpass-through formeterBatch/meterRetry. Considered, cut to keep the diff aligned with what's already published as 1.2.1. Follow-up if desired — would be 1.2.2.OutcomesClient,index.ts,mandate.ts,errors.ts.Test plan