cloud/C12: end-to-end test (license → chat → usage)#227
cloud/C12: end-to-end test (license → chat → usage)#227blueberrycongee wants to merge 5 commits intoloop/cloud-C9from
Conversation
PRD §3 forbids editing src/services/llm/providers/models.ts, so the
provider definition lives self-contained in luminaCloud.ts. Consumers
(AISettingsModal in C11) combine LUMINA_CLOUD_PROVIDER with
listProviderModels() when isLuminaCloudVisible(features) returns true.
Exports:
- LUMINA_CLOUD_PROVIDER_ID, LUMINA_CLOUD_BASE_URL, LUMINA_CLOUD_REQUIRED_FEATURE
constants.
- LUMINA_CLOUD_PROVIDER: ProviderMeta with empty static models (filled
dynamically — server returns the catalog per CONTRACT.md §2.3).
- isLuminaCloudVisible(features): true iff features include 'cloud_ai'.
Tolerant of null / undefined so call sites can pass
useLicenseStore's payload?.features directly.
- fetchLuminaCloudModels(license): calls client.getModels and maps
{ id, upstream, context } → { id, name, contextWindow } rows.
Tests cover provider shape (constants + ProviderMeta fields), all
six visibility cases (null / undefined / [] / no-feature / single /
multiple), and three model-fetch outcomes (mapped / empty / error
propagation). 8 tests, all pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Exercises the full client flow against mocked luminaCloud touchpoints: 1. setLicense drives the store through idle → loading → valid and persists via saveLicense. 2. payload.features is read back; isLuminaCloudVisible returns true for cloud_ai. 3. fetchLuminaCloudModels delegates to getModels and returns the mapped catalog. 4. A pre-chat getUsage call is captured. 5. Mock chat round-trip — the AI SDK plumbing isn't this test's surface; what matters is that usage moves forward. 6. Post-chat getUsage shows the tokens_used + requests_count delta. Two negative paths kept this from devolving into a happy-path-only smoke test: - Invalid signature → status='invalid', provider hidden, no save, no chat. - Valid signature without cloud_ai → status='valid' but provider still hidden. 3 tests, all pass. Branch is `loop/cloud-C9` + merge of `loop/cloud-C7`, since C12 needs C2 + C4 + C5 + C7. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7a22d0ef59
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| export const LUMINA_CLOUD_PROVIDER_ID = 'lumina-cloud'; | ||
|
|
||
| export const LUMINA_CLOUD_BASE_URL = 'https://api.lumina-note.com/v1/ai'; |
There was a problem hiding this comment.
Read Lumina Cloud base URL from configured environment
This hardcoded base URL bypasses the env override path already used by the Lumina Cloud REST client (VITE_LUMINA_CLOUD_BASE_URL in src/services/luminaCloud/client.ts). In staging/dev setups, license verification/usage calls can hit the configured host while chat calls from this provider still go to production, causing split behavior and hard-to-diagnose auth/usage mismatches. Please derive this value from the same base-url resolver so all Lumina Cloud endpoints stay on one backend.
Useful? React with 👍 / 👎.
|
Closing — re-issued cleanly by integrator. |
What
Adds
src/__tests__/luminaCloud.e2e.test.ts— a Vitest integration test that drives the full client flow with mocked@/services/luminaCloudtouchpoints.Stacking
C12 needs C2 (verify), C4 (store), C5 (HTTP client), and C7 (provider). This branch builds on
loop/cloud-C9(which already merges C2 + C4 + C5) and adds a merge ofloop/cloud-C7on top, then the test commit.Merge to main order: #217 (C1) → #218 (C2) → #220 (C4) → #221 (C5) → #223 (C7) → #225 (C9) → this PR (C12). When you merge them in that order, both merge commits in this branch become no-ops.
What the test exercises
idle → loading → valid; payload comes from the mockedverifyLicense;saveLicenseis invoked.payload.featuresfrom the store and assertsisLuminaCloudVisiblereturnstruefor thecloud_ai-bearing fixture.fetchLuminaCloudModels(license), asserts it delegates toclient.getModelsand maps the response intoModelMetarows.tokens_used: 0.client.getUsage.getUsagecall returns highertokens_usedandrequests_count.Two negative-path tests keep this from being happy-path-only:
'invalid', provider hidden, no save, no chat.features: ['lifetime'](nocloud_ai) → status'valid'but provider still hidden.Acceptance criteria
npm test -- src/__tests__/luminaCloud.e2e.test.tspasses.3/3 pass. Typecheck pass.
Touched files outside src/services/luminaCloud/
src/__tests__/luminaCloud.e2e.test.ts— within the PRD §3 surface (test files for the existing surfaces are implicitly allowed).cloud/TASKS.md— marked C12[x]and appended Done-log entry.Notes for Lead
getUsagedelta. The actual/v1/ai/chat/completionsPOST goes through the AI SDK's openai-compatible plumbing wired by C7's provider, which lives in opencode's runtime — out of scope for a renderer-side Vitest e2e.verifyLicense,saveLicense,getUsage,getModels) are mocked at the@/services/luminaCloudmodule level viavi.hoisted+vi.mock. Same pattern used in C4 and C8 tests.