Skip to content

feat(web): React UI v2.0 — Phase 2 Tasks 21-22 (TS types + apiFetch)#20

Merged
aksOps merged 3 commits into
mainfrom
feat/web-phase-2-batch-a
May 16, 2026
Merged

feat(web): React UI v2.0 — Phase 2 Tasks 21-22 (TS types + apiFetch)#20
aksOps merged 3 commits into
mainfrom
feat/web-phase-2-batch-a

Conversation

@aksOps

@aksOps aksOps commented May 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase 2 Batch A of React UI v2.0 — the foundational types and HTTP client that downstream hooks (Tasks 23-31) build on.

  • Task 21web/src/api/types.ts (90 lines): hand-authored TypeScript types mirroring /api/v1/* schemas — Session, AgentRun, ToolCall, AgentDefinition, SessionEvent, SessionFullBundle, UiHints, AppView, ApiError. v2.1 should generate from OpenAPI.
  • Task 22web/src/api/client.ts + tests (3 tests): apiFetch<T>(path, options) with /api/v1 prefix, localStorage['asr.token']Authorization: Bearer …, structured ApiClientError ({status, code, message, details}) on 4xx/5xx.
  • Fix-upToolCall.status literal union widened to include executed_with_notify and timeout (backend ToolStatus emits these; the spec missed them). Without this fix, Task 25's reducer would hit type narrowing errors when switching on event payloads.

Validation

  • cd web && npm install → 0 vulnerabilities
  • npm run typecheck → exit 0
  • npx vitest run33 passed / 0 failed (Phase 1's 30 + 3 new client tests)
  • npm run build → clean

Nothing touches src/runtime/ — no dist/app.py regen.

Implementation note

client.ts uses await res.clone().json() (not await res.json()) when reading error bodies. This handles the test pattern where the same Response instance is consumed twice — without .clone(), bodyUsed=true after the first read silently drops the error code. It's a safer choice in production too (keeps the body readable for retry/logging if needed).

Type drift surfaced for future follow-up

The backend cross-check found a few smaller drifts that don't block Phase 2 but should be addressed before v2.0-rc1:

  • Session.token_usage — backend has it (session-level rollup); TS doesn't. Apps surfacing rolled-up token totals would need it.
  • Session.status — backend is open str; TS narrows to a Literal union. The narrowing may miss edge statuses.
  • AgentRun.token_usage — TS marks optional; backend always present (default_factory=TokenUsage). Intentional per the spec, but TS could tighten.

These are tracked as latent items and don't change wire compatibility.

Test plan

  • Vitest: 33/33 pass
  • Typecheck: exit 0
  • Build: clean
  • Pytest backend stays green (no backend changes)
  • CI: lint + type + test + sonar + bundle + skill-lint
  • CI: SonarCloud quality gate

🤖 Generated with Claude Code

aksOps added 3 commits May 16, 2026 04:10
…meout)

The TS spec from the design doc omitted two literal status values the
backend actually emits. Adding them now so Task 25's reducer can switch
on the full set without TS narrowing errors. The 'auto_rejected' value
in the spec is kept — the UI synthesizes it on HITL timeout per §16.5.
@sonarqubecloud

Copy link
Copy Markdown

@aksOps aksOps merged commit 1548458 into main May 16, 2026
9 checks passed
@aksOps aksOps deleted the feat/web-phase-2-batch-a branch May 16, 2026 10:50
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