- bump @dcloudio/* to 3.0.0-alpha-5020320260803001 to match the
HBuilderX-Alpha 5.23.2026080313 debug base (fixes HTML5+ Runtime
5.14/5.23 mismatch dialog on device)
- add .env.development with VITE_SMS_VERIFICATION_ENABLED=true so the
SMS code field shows in run mode; on-device debug talks to prod
backend where verification and the pilot fixed code are enabled
- update MOBILE_APP_PACKAGING.md toolchain line
73712994 disabled voice-first on native by gating the TTS preload behind
!isNativeAppRuntime(), which left App users with the degraded text bubble
plus a 播报 button. The voice-line, 转文字 toggle and 收起全文 markup were
still present but unreachable.
Re-enable the preload on every platform and open the transcript when the
message is created, so the answer is readable while synthesis runs.
Collapse the transcript when playback starts rather than when synthesis
finishes: on-device synthesis settles in 2-6s, so collapsing on ready
pulled the answer away mid-sentence. transcriptPinned records a manual
toggle so the automatic collapse never overrides the reader.
Bound the preparing bubble at 20s (the upstream DashScope ceiling) so a
stalled synthesis degrades to the plain text bubble instead of showing an
endless placeholder duration.
Replace the tautological assertion that pinned the previous behaviour by
matching source strings with assertions on the behaviour itself.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Covers the App-Plus batch in this series: renderjs realtime practice, request
timeout abort, App-Plus date/query API replacements, and on-demand native
voice. Native permissions and plugins are unchanged, so this ships as a normal
cloud rebuild.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
On native App the eager TTS request delayed the answer bubble: the message was
created in `preparing` state, so the text stayed behind a voice line that was
still waiting on a round trip.
Skip the preload when `isNativeAppRuntime()`, marking the voice `unavailable`
so the text and citations render immediately. The existing `unavailable`
branch already exposes a play button that calls `toggleAnswerSpeech`, so voice
stays reachable on demand instead of being dropped. H5 keeps preloading.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
App-Plus has no WebRTC or getUserMedia in the logic layer, so realtime
practice was H5-only and the native entry had to advertise a record-then-
transcribe downgrade.
Move the media/WebRTC engine into `realtime-browser-engine.js` and drive it
from `RealtimePracticeAppBridge.vue`, whose renderjs script runs inside the
system WebView where those APIs do exist. The logic layer keeps the
authenticated calls: SDP exchange and `search_knowledge` tool invocation stay
server-proxied, so the access token is never handed to the view layer. Both
sides talk over the renderjs bridge only in session payloads the server
already assembled.
Verified against a real App build (`app-renderjs.js` holds RTCPeerConnection
and getUserMedia; `app-service.js` holds the SDP endpoint, renderjs side has
zero hits). Microphone permission, live transcription, remote playback,
foreground/background switching and disconnect fallback still require Android
and iOS device verification.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`URLSearchParams` is absent from the App-Plus JS core, and
`toLocaleDateString('sv-SE', { timeZone: 'Asia/Shanghai' })` depends on full
ICU data that the App runtime does not ship, so the work-result pages built
either a broken query string or the device-local date.
Build query strings with `encodeURIComponent`, and centralise the business day
in `currentShanghaiDate()`, which shifts the epoch by a fixed UTC+8 offset
before slicing the ISO date. Asia/Shanghai has no DST, so the fixed offset is
exact rather than an approximation.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Some uni-app platforms ignore the `timeout` option, leaving the returned
promise pending forever and hanging the calling page with no error path.
Drive the deadline locally: keep a single-shot `finish` guard so success,
failure and timeout can only settle once, and on timeout call `task.abort()`
before rejecting so the in-flight request is released instead of leaking.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`@dcloudio/uni-app-plus` was never declared, so `uni build -p app` silently
fell back to an H5 shell: exit code 0, `DONE Build complete.`, but the output
was only `index.html` (still carrying the `/h5/assets/...` base path) with no
`app-service.js`, `app-renderjs.js` or `manifest.json`. Because
`docs/MOBILE_APP_PACKAGING.md` lists that command as a local verification
step, App platform code was reported as built without ever reaching the App
compiler.
Declare the compiler at the same version as the other `@dcloudio` packages,
guard the version alignment in `tests/app-packaging.test.mjs`, and document
that success is judged by the emitted artifacts, not by the DONE line.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>