Skip to content

feat(sdk): MeterClient batching, retry, preserved idempotency (1.2.1) - #32

Open
Z333Q wants to merge 3 commits into
mainfrom
opt2-p0-meterclient-batching
Open

feat(sdk): MeterClient batching, retry, preserved idempotency (1.2.1)#32
Z333Q wants to merge 3 commits into
mainfrom
opt2-p0-meterclient-batching

Conversation

@Z333Q

@Z333Q Z333Q commented Jul 4, 2026

Copy link
Copy Markdown
Owner

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 new POST /api/v2/meter/events/batch. Per-event failures land in results with ok: false so callers can retry only the events that need it.
  • Optional buffered mode: constructor batch: { maxEvents, maxLatencyMs }, plus enqueueEvent(event) and flush(). Without a batch config the client behaves as before.
  • fetchWithRetry wraps every meter HTTP call. Exponential backoff with full jitter on network errors and 5xx. Defaults 3 / 200ms / 5000ms, all constructor-overridable. 429 is not retried and surfaces immediately as RATE_LIMITED.

Per-event request_ids are preserved verbatim across retries. The router UPSERTs on (tenant_id, request_id), so duplicate submissions produce the same event_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 MeterClient directly), OutcomesClient reference.

What's not in this PR

  • P402Client/P402Config pass-through for meterBatch/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.
  • No changes to OutcomesClient, index.ts, mandate.ts, errors.ts.

Test plan

  • tsc --noEmit clean
  • vitest run → 30 passed (17 pre-existing + 13 new: batch, buffered mode, retry)
  • tsc + node scripts/smoke-esm.mjs → SMOKE OK
  • npm pack produces p402-sdk-1.2.1.tgz with the six modules
  • Functionally identical to the tarball already at npm view @p402/sdk@1.2.1

ZA-KIU added 3 commits July 4, 2026 14:40
… (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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants