Skip to content

feat(quantum): add sidebar dashboard with credits, jobs, and compute status#7

Open
Kenny-Heitritter wants to merge 12 commits intofeat/codeq-telemetryfrom
feat/quantum-sidebar
Open

feat(quantum): add sidebar dashboard with credits, jobs, and compute status#7
Kenny-Heitritter wants to merge 12 commits intofeat/codeq-telemetryfrom
feat/quantum-sidebar

Conversation

@Kenny-Heitritter
Copy link
Member

Summary

  • Add a quantum resource dashboard to the TUI sidebar and footer, showing qBraid credits balance, active quantum jobs, and compute instance status
  • Build a centralized reactive state store (quantum/state.ts) using Instance.state() for per-instance isolation, with Bus events for TUI reactivity
  • Implement adaptive background polling via the Scheduler system (credits: 60s, jobs: 30s when active, compute: 60s)
  • Wire quantum tools to trigger state refresh after submit/cancel/get_result so the sidebar updates immediately

Design

Progressive disclosure — minimal when idle (just ⚛ qBraid $42.50 in footer), expands when resources are active (shows job rows, compute status in sidebar section).

Three pillars mirroring the qBraid account page:

  1. Credits — qBraid + AWS balance from /billing/credits/balance
  2. Quantum Jobs — active jobs with device, status, shots from /jobs
  3. Compute Instances — status from /compute/servers/status (management is future work)

New Files

  • quantum/state.ts — Centralized state store with Instance.state(), Bus event quantum.state.updated, refresh functions for credits/jobs/compute
  • quantum/poller.ts — Scheduler-based adaptive background polling with Instance.state() for per-instance timestamp tracking
  • cli/cmd/tui/component/quantum-status.tsxQuantumSidebarSection (collapsible), QuantumFooterIndicator (compact), useQuantumState() hook

Modified Files

  • quantum/client.ts — Added getCredits(), getComputeStatus(), listActiveJobs(), isConfigured(), CreditsBalanceSchema, ComputeStatusSchema
  • quantum/tools.ts — Added state refresh triggers after submit/cancel/get_result, fixed getCredits return type
  • quantum/index.ts — Added QuantumState and QuantumPoller exports
  • project/bootstrap.ts — Added QuantumPoller.init() + QuantumState.refreshAll() calls
  • cli/cmd/tui/routes/session/sidebar.tsx — Added qBraid section between Context and MCP
  • cli/cmd/tui/routes/session/footer.tsx — Added QuantumFooterIndicator between permissions and LSP

Architecture Patterns

  • Instance.state() for all per-instance state (matches all 25+ existing modules)
  • BusEvent.define() with explicit Zod schema z.object({}) for signal events
  • Scheduler for background polling with adaptive intervals
  • useTheme() for typed RGBA color access (no type-erasing helper functions)

Commits (2)

feat(quantum): add sidebar dashboard with credits, jobs, and compute status
refactor(quantum): consolidate schemas and remove dead code

Stats

9 files changed, 546 insertions(+), 7 deletions(-)

Depends On

…status

Add quantum resource dashboard to the TUI sidebar and footer:

- QuantumState: centralized reactive store tracking credits balance,
  active jobs, and compute instance status via Bus events
- QuantumPoller: Scheduler-based adaptive polling (credits/compute 60s,
  jobs 30s when active) with auto-detection of API key mid-session
- QuantumSidebarSection: collapsible sidebar panel showing credit balance,
  active job rows with status dots and elapsed time, compute status
- QuantumFooterIndicator: compact footer indicator (active QPU count)
- Extended client.ts with getCredits (billing/credits/balance endpoint),
  getComputeStatus, listActiveJobs, and Zod schemas for validation
- Fixed getCredits return type mismatch in estimate_cost tool
- Tools (submit, cancel, get_result) trigger state refresh for immediate
  sidebar updates after quantum operations
- Wired poller and initial refresh into InstanceBootstrap
- Move CreditsBalanceSchema and ComputeStatusSchema to the schema
  section at the top of client.ts, alongside QuantumDeviceSchema,
  QuantumJobSchema, and JobResultSchema
- Remove redundant formatCredits branch (n >= 10 and default were
  identical)
…endency

- submitJob: send deviceQrn+program instead of device+openQasm (API v1 schema)
- state: use module-level singleton instead of Instance.state() so it works
  inside SolidJS reactive computations (no AsyncLocalStorage context there)
- getDevice: unwrap data envelope for single-device API response
- build: fallback to 'dev' channel when git is not available in PATH
…, and interference spinner

- Add qBraid API key startup dialog (dialog-qbraid-auth.tsx) shown after
  telemetry consent on first launch, with sequence: consent → auth → provider connect
- Fix quantum client wire format: correct auth header (X-API-Key), endpoint
  paths (/devices, /jobs, /billing/credits/balance), response unwrapping (.data),
  and Zod schemas with transforms for API normalization
- Fix event timing race: register RPC listener during init() instead of
  onMount() to prevent lost events; add sdk.latest Map for event caching
- Fix quantum sidebar: credits displayed as 'X credits' not dollars,
  updatedAt guard prevents stale events, cached event read on mount
- Add interference/diffraction animation engine for quantum-themed spinner
- Simplify telemetry consent dialog text and auth resolution
- Add QBRAID_DEFAULT_API_URL constant with QBRAID_API_URL env var override
- Add includeUsage flag for qBraid provider
- Fix branding apply.ts URL replacement ordering
- Normalize CodeQ → Codeq capitalization in comments
- Add fork rationale documentation and build/smoke-test scripts
… tools

Add 8 new tools for deep qBraid platform integration:

- quantum_environments: list/search software environments (Qiskit, Cirq, CUDA-Q, etc.)
- quantum_environment_packages: get full package list for an environment
- quantum_compute_profiles: list available server configs (free to GPU)
- quantum_compute_status: check if compute server is running
- quantum_compute_start: launch a compute server (with permission prompt)
- quantum_compute_stop: stop running server (with permission prompt)
- quantum_account: show credits, AI chat quota, disk usage, org/subscription info
- quantum_job_circuit: get ASCII circuit diagram for a submitted job

Also adds queue depth, description, and modality to device schema for
richer device listing output.

All endpoints verified against live qBraid API v1.
Add quantum/jupyter.ts — new module for JupyterHub integration:
- Session token resolution from qBraid API
- Contents API: list, read, write files on remote server
- Kernel WebSocket execution: start kernel, send execute_request,
  collect stdout/stderr, clean up kernel

New tools (5):
- quantum_remote_exec: execute Python code on cloud server
- quantum_remote_files: list files on remote workspace
- quantum_remote_read: read a file from remote server
- quantum_remote_write: write a file to remote server
- quantum_remote_kernels: list available Jupyter kernels

The demo flow: start a compute server, write a quantum circuit,
execute it remotely, get measurement results — all from the agent.

Verified against live staging: session tokens, Contents API (201),
and WebSocket kernel execution all working on lab-v2-staging.
Production (account.qbraid.com) requires Authorization: Bearer,
while staging (pr-441 Cloud Run) requires X-API-Key. Send both
headers so the provider works against either environment.
The AI provider was only reading the API key from the auth store
(~/.local/share/codeq/auth.json), ignoring QBRAID_API_KEY env var.
This meant staging couldn't override the key. Now QBRAID_API_KEY
takes priority over the stored key, matching the quantum client.
Redesign compute state from single-instance to array of ComputeInstance,
preparing for multi-server support via JupyterHub named servers.

State changes:
- State.compute (single object) -> State.instances (ComputeInstance[])
- ComputeInstance tracks: name, profile, status, clusterId, startedAt,
  rate, kernels count, and executing snippet

Sidebar changes:
- InstancesSection replaces ComputeSection, shows all live instances
- Each instance row: colored status dot, profile name, uptime, cost
  rate, kernel count, and current execution snippet
- Footer indicator shows both QPU job count and compute instance count

Client changes:
- listServers() calls new GET /compute/servers endpoint
- startServer/stopServer accept optional serverName for named servers
- refreshCompute tries listServers first, falls back to legacy status

Tool changes:
- compute_start optimistically shows instance in sidebar immediately
- remote_exec tracks execution in sidebar (snippet + kernel count)
- compute_start: add optional name param for named instances
- compute_stop: add optional name param to target specific instance
- compute_status: use listServers to show all instances
- remote_exec/files/read/write/kernels: add optional instance param
- client.getSessionToken: pass serverName for named instances
- All tool descriptions updated to reflect multi-instance capability
getDevice, submitJob, getJob, getResult were passing the full
{ success, data } envelope to Zod schemas instead of unwrapping
the inner data field first. This caused validation errors like
'expected string, received undefined' for fields like name/vendor/status.
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.

1 participant