feat(mc): Pool B resilience suite (A+B+C+D)#30
Merged
Conversation
Bundles four operator-visible improvements to the Pool B inference stack that together let WaveX run as a SaaS instead of a self-hosted toy. Companion to #28 (Pool B Health widget + claude CLI prereq). A. Composio managed mode (operator-managed key, not customer-managed) ───────────────────────────────────────────────────────────────────── The directory modal at /<company>/connectors used to demand each customer paste their own Composio API key. For a hosted WaveX deploy that's wrong: the operator runs the Composio account, the customer just gets the connectors as part of their subscription tier. - New env: WAVEX_COMPOSIO_MANAGED=1 on wavex-os-server - /api/connectors/setup-status now returns { managed: boolean } - ConnectorsSidebar's SetupScreen gate skips the key-entry modal when managed: true — falls through to the catalog (or degraded catalog when Composio is transiently down) instead of demanding a key the customer doesn't have Self-hosted users keep BYOC by leaving WAVEX_COMPOSIO_MANAGED unset. B. UUID→slug translation in plugin worker (fixes "0/0 ready" + fleet showing 0 agents even when 35 are alive) ───────────────────────────────────────────────────────────────────── The plugin context gives the worker paperclip's company UUID, but wavex-os-server's loadCompanyManifest() / getOnboardingDir() index by the wavex slug (~/.wavex-os/instances/<slug>/). Every single ${base}/api/.../<uuid>/... call was silently returning [] because the manifest lookup failed. Diagnosed live: /api/companies/<uuid>/agents → [] /api/companies/<slug>/agents → 35 agents /api/companies/<uuid>/agents on paperclip core → 35 agents - New helper resolveWavexSlug(uuid) in worker.ts that calls paperclip on first miss, caches the mapping in-process (immutable post-finalize) - Replaces every `const id = String(companyId ?? "")` with the async resolver (~30 sites mechanical, plus the inception-status handler's inline pattern) - Falls back to the raw input on lookup failure for partial-wiring test cases — degraded behavior is the same as before this change Net effect: Inception Status sidebar now shows the real agent count, Mission Control's Stream / Scoreboard / Map all hydrate correctly, everything that hit ${base}/api/.../<id>/... starts working. C. Inference life bar + throttle slider in Pool B Health ───────────────────────────────────────────────────────────────────── Operator wants a glance check before triggering big customer flows — "am I about to blow my Claude Max quota?" — plus a control surface to throttle Pool B request rate to spread load. - New endpoint GET /api/pool-b-health/operator-quota returning {tokens_used_24h, tokens_used_7d, tokens_used_30d, cost_usd_*, requests_24h, requests_7d, last_inference_at}. Aggregates wavex_os.usage_ledger rows over the windows; 30s cache. - New worker data registration pool-b-health-operator-quota. - UI: life bar with green/yellow/red zones (cap at $5/day soft visual ramp), 24h/7d/30d numeric readout, throttle slider 1-120 req/min persisted to localStorage. Throttle ENFORCEMENT (queue/reject above cap on the inference-server side) lands in a follow-up PR — for now the slider is a planning surface. The life bar is fully live. D. Supabase Edge Function: Pool B inference fallback ───────────────────────────────────────────────────────────────────── When the operator's Mac is offline or rate-limited, the customer's 60s Realtime timeout currently fails silently (empty pillar suggestions, hardcoded narrate copy). This PR adds an Edge Function that the consumer-side cloudInference() can call as a fallback after its existing timeout fires: POST /functions/v1/wavex-inference-fallback body: { prompt, max_output_tokens, purpose, model? } → { ok: true, content, usage, source: "fallback" } - Auth-gated: requires the caller's JWT + an active/trialing subscription. Free tier returns 402 — no anonymous Anthropic calls on the operator's dime. - Defaults to claude-haiku-4-5 (cheap; ~$0.005 per pillar-suggest). Whitelist also allows haiku-4-5-20251001 + sonnet-4-6. - Logs each call to wavex_os.usage_ledger with device_id=NULL so fallback usage shows up in the Pool B Health widget separately from Mac-served calls. - Returns 503 with structured error if ANTHROPIC_API_KEY is not set in Supabase project secrets — browser gracefully falls back to its existing failure mode. Consumer-side cloudInference.ts update (browser calls this on timeout) lands in a follow-up PR in wavex-experience-architect. Deploy steps for D: 1. Generate Anthropic API key at console.anthropic.com (separate from CLI session token — backend use only). 2. supabase secrets set ANTHROPIC_API_KEY=sk-ant-... 3. supabase functions deploy wavex-inference-fallback Verification ───────────────────────────────────────────────────────────────────── - pnpm --filter @wavex-os/paperclip-plugin-wavex build → 240.0kb dist - packages/wavex-os-server tsc → clean - Diff: 7 files, ~330 insertions, ~30 deletions - Test CI runs on push Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
Four operator-visible improvements that together let WaveX run as a SaaS, not just a self-hosted toy. Each is independently shippable; bundling because they share verification surfaces (Pool B Health tab, mission control, connectors directory).
wavex-os-serverenv +ConnectorsSidebarUI/api/pool-b-health/operator-quotaendpointsupabase/functions/wavex-inference-fallback/A · Composio managed mode
Customers shouldn't paste their own Composio API key. Operator runs Composio, customer is billed for it via subscription tier.
WAVEX_COMPOSIO_MANAGED=1on the server/api/connectors/setup-statusreturnsmanaged: booleanmanaged: true— falls through to the catalog (or degraded catalog if Composio is transiently down)B · UUID→slug translation (THE big bug fix)
Diagnosed live:
Plugin context gives paperclip's UUID;
wavex-os-serverkeys by the wavex slug (the~/.wavex-os/instances/<slug>/dir name). Every${base}/api/.../<id>/...call was silently returning[].resolveWavexSlug(uuid)calls paperclip on first miss, caches the mapping in-process (immutable post-finalize)const id = String(companyId ?? "")toconst id = await resolveWavexSlug(...)Net effect: Inception Status sidebar shows real agent count; Mission Control's Stream/Scoreboard/Map hydrate correctly; everything downstream of
${base}/api/.../<id>/...starts working.C · Life bar + throttle slider
Operator wants a glance check before triggering big customer flows — "am I about to blow my Claude Max quota?" — plus a control surface to throttle.
GET /api/pool-b-health/operator-quotareturns{tokens_used_*, cost_usd_*, requests_*, last_inference_at}over 24h / 7d / 30d windowsD · Supabase Edge Function inference fallback
When the operator's Mac is offline or rate-limited, the customer's 60s Realtime timeout currently fails silently. This adds a fallback the consumer can call:
claude-haiku-4-5-20251001(~$0.005 per pillar-suggest)usage_ledgerwithdevice_id=NULLso fallback usage is visible separately in the Pool B Health widgetANTHROPIC_API_KEYsecret missing — browser gracefully no-opsConsumer-side update (cloudInference.ts calling this on timeout) lands in a follow-up PR in
wavex-experience-architect.Deploy steps for D
supabase secrets set ANTHROPIC_API_KEY=sk-ant-...supabase functions deploy wavex-inference-fallbackWhat's NOT in this PR (next-up follow-ups)
Verification
pnpm --filter @wavex-os/paperclip-plugin-wavex build→ 240.0kb distpackages/wavex-os-servertsc → clean🤖 Generated with Claude Code