Commit Graph
219 Commits
Author SHA1 Message Date
admin 46950b39fe chore(mobile): bump version to 0.1.20 (120) - device already runs 0.1.19 (119) from an older 08-03 build 2026-08-05 09:24:35 +08:00
admin 6b8c89bcdb feat(mobile): owner identity selector on realtime practice
- default persona falls back to owner-calm; picker below persona cards
  (compact single row), default own community via defaultProfileId,
  storage persistence incl. explicit none, hidden on empty/failure
- profileId passed to realtime session creation when selected
2026-08-05 03:18:50 +08:00
admin 8f275b5a7a feat(mobile): show new ask sources and direct citation navigation
- citation chips: 正式经验 (CASE_EXP) / 同事经验·有奖征答 (COMMUNITY)
- citation navigation: CASE_EXP opens case detail via ?caseId=,
  COMMUNITY goes straight to question detail via community-question
  detailRef, falling back to the question list
- disable human-help action when the answer was already marked helpful
  (server would 409)
2026-08-05 02:46:07 +08:00
admin 08e1ad33b6 chore(mobile): align uni-app compiler with HBuilderX 5.23 alpha
- 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
2026-08-05 01:28:16 +08:00
admin be94b68a92 chore(mobile): bump version to 0.1.18 (118) for ask-page UX release 2026-08-05 01:02:29 +08:00
admin 1fc99293f6 feat(mobile): render evidence levels and route actions in ask page
- normalize evidenceLevel/uncoveredPoints/nextActions from agent response
- GUIDANCE banner (reference experience, non-formal), PARTIAL uncovered
  points list, ROUTE compact action buttons (human help / direct channel /
  web research); legacy responses render unchanged
- one-tap human help on ROUTE: auto-submit down feedback (NO_ANSWER,
  fragment-less allowed by backend) then existing confirm + idempotent
  publish chain
- direct channel page supports ?channel= preselection
2026-08-05 00:53:00 +08:00
key ba0c718975 feat(aihr): enable grounded agent active runtime 2026-08-04 22:29:13 +08:00
key 12fc9fdddc feat: add query observability and collation safeguards 2026-08-04 02:15:03 +08:00
key 721839c847 feat(aihr): harden finance RAG retrieval and evidence gates 2026-08-03 22:34:18 +08:00
key a07bbcca07 fix: support authenticated video citation playback 2026-08-02 22:04:09 +08:00
key 6ad8a017a4 feat(aihr): close functional checklist gaps 2026-08-02 12:15:45 +08:00
key 699cc08050 feat: govern knowledge assets and source citations 2026-08-02 01:43:43 +08:00
key adedcb4200 release(android): close 0.1.17 device candidate 2026-07-30 21:02:56 +08:00
key c16a3e83d7 feat(release): close handler and microphone gaps 2026-07-30 12:01:45 +08:00
key 380d8e6e32 fix(mobile): converge work report confirmation 2026-07-30 00:14:42 +08:00
key 5027bef32d fix(mobile): support Android system file picker 2026-07-29 23:52:44 +08:00
key 6ba7df863f chore: add UI audits and reconcile release docs 2026-07-29 16:10:46 +08:00
key 70e5516ff3 fix(release): close fixed-code mobile auth gaps 2026-07-29 11:59:30 +08:00
key b9e0878926 fix(android): share public legal URLs with cloud builds 2026-07-29 10:07:22 +08:00
key 7f3357c7a1 fix(android): use login consent instead of native privacy prompt 2026-07-29 09:59:41 +08:00
key dc20b92061 fix(mobile): recover direct channels after network failure 2026-07-29 02:31:19 +08:00
key cb928edafd fix(mobile): handle file picker cancellation 2026-07-29 02:01:45 +08:00
key ba68fc8326 release: harden Android network security 2026-07-29 01:13:18 +08:00
key 9ea5d79a62 release: prepare August 1 Android RC 2026-07-29 00:35:15 +08:00
key 9ae5f750c8 fix: align Windows dev, App compiler, and ASR 2026-07-26 21:27:37 +08:00
admin f57e0a53c6 feat(mobile): expand TTS voices and align App SDK 2026-07-26 17:05:43 +08:00
admin 94ee29f59c fix(speech): write native TTS temp file as binary and clean it up
App-Plus 的 plus.io FileWriter 只接受字符串:write 写文本,writeAsBinary 收
base64。原先传 Blob 会被原生桥接序列化成空内容,落地 0 字节且照样回调
onwriteend,InnerAudioContext 静默播完、不报错,表现为"界面正常但没有声音"。
改用 writeAsBinary 并在 onwriteend 里复核 size > 0,让写盘失败能被暴露。

清理侧同一处存在文件泄漏:播放要 convertLocalFileSystemURL 转出的 file://
绝对路径,而 resolveLocalFileSystemURL 删除只认 `_doc/xxx.mp3` 相对路径。
原先只回传前者,拿它去 resolve 解析不到,remove() 从不执行,且 catch 静默,
临时 mp3 逐句堆积。改为返回 { playbackUrl, plusPath } 两个路径,清理失败加告警。

真机验证(Android 10 / io.dcloud.HBuilder):落盘 80251 字节,ID3+LAME 头,
MPEG layer III 160 kbps 24 kHz 单声道,播完文件自动删除。

顺带把测试里 MP3 头字面量的真实 NUL 字节改为 \x00 转义(运行时字节不变),
此前 git 将该测试文件判为二进制,diff 无法审阅。
2026-07-26 12:10:50 +08:00
adminandClaude Opus 5 d84ad87cb6 fix(sop): restore voice-first replies on App without withholding text
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>
2026-07-26 02:36:14 +08:00
adminandClaude Opus 5 7096545e82 fix(mobile): translate microphone errors and pre-request permission
实时陪练失败时,getUserMedia 抛出的 Chromium 英文原文会直接透给用户(真机实测见过
"Could not start audio source"),既不可读也不含任何可执行指引。新增
utils/microphone.ts 把权限、设备占用、无设备、非安全上下文四类底层错误翻译成中文
引导;业务层自己抛的中文文案原样透出,未识别的错误回落到原有通用提示。

同时在建会话之前主动申请 RECORD_AUDIO,并在 manifest 显式声明该权限。

需要说明:此权限预申请是防御性的。真机核查 RECORD_AUDIO 已授予、APK 本就声明该权限、
实时链路可正常跑通,先前那次 "Could not start audio source" 是麦克风被其他应用占用
的瞬时故障,不是权限缺陷。未在"权限未授予"的设备上实测过 WebView 是否会自行弹出
Android 运行时授权框,故此调用在已授权设备上为无害空转;若确实不弹,则它是唯一授权入口。
manifest 声明同样只为防未来模块调整导致权限丢失。

新增 6 项单测覆盖错误映射与授权分支(共 168 项通过)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 00:58:40 +08:00
adminandClaude Opus 5 788a2abbe4 fix(mobile): avoid status bar overlap on custom-nav pages
全局 navigationStyle 为 custom,页面需自行避让状态栏,但四处顶部内容仍被状态栏
压住:练习页标题与对话页标题、我的页顶部卡片、问答页头部。

避让不能走 CSS:env(safe-area-inset-top) 在 Android WebView 恒为 0(该值本是
iOS 刘海概念,Chromium 仅在配置 display-cutout 时才上报),uni-app 注入的
--status-bar-height 实测在 App 端同样取不到,两者都会静默回落成 0,造成"构建产物
里改动存在但运行时无效"。改由 utils/safe-area.ts 读
uni.getSystemInfoSync().statusBarHeight,各页面以内联样式绑定 padding-top。

profile 页同时把 min-height 从 100vh 改为 100%:叠加状态栏内边距后 100vh 会
溢出一屏高度产生多余滚动。

真机(vivo V2443A,720x1600,状态栏 72px)像素验证:修复前状态栏下缘 60-80px 带内
有 872 个文字像素,修复后四处均为 0。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 00:58:18 +08:00
adminandClaude Opus 5 4fc0c1f5f8 chore(mobile): bump App version to 0.1.5 (versionCode 105)
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>
2026-07-25 23:59:05 +08:00
adminandClaude Opus 5 73712994c6 fix(mobile): stop preloading answer TTS on native App
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>
2026-07-25 23:58:19 +08:00
adminandClaude Opus 5 5cf7ce5847 feat(practice): run realtime practice on App-Plus through renderjs
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>
2026-07-25 23:58:10 +08:00
adminandClaude Opus 5 3055d2bec9 fix(mobile): replace App-Plus unsupported date and query APIs
`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>
2026-07-25 23:57:06 +08:00
adminandClaude Opus 5 27f4cdac70 fix(mobile): abort uni.request when the platform timeout does not fire
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>
2026-07-25 23:56:56 +08:00
adminandClaude Opus 5 a3a5cf944e build(mobile): declare App platform compiler to stop build:app false green
`@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>
2026-07-25 23:56:47 +08:00
admin ab3af277c1 fix(speech): convert base64 TTS data URI before playback per platform
后端 TTS 以 data: URI 返回 base64 mp3(生产实证为合法 LAME mp3),但
App-Plus 的 InnerAudioContext 不支持 data: URI,iOS Safari/微信 webview
也常静默失败,统一报"语音播放失败"。播放前按平台转换:H5 转 Blob URL,
App 端经 plus.io 落 _doc/ 临时文件后播放 file:// 路径,播完清理;Blob 不可
用时退回原始 data: URI。竞态守卫与缓存语义保持不变,158 单测全绿。
2026-07-25 20:37:30 +08:00
admin bb8b2dde7e fix(exam): replace unfounded 4-char title rule with explicit validation messages
- 考试名称仅要求非空,移除无依据的至少 4 字限制;保留及格分 1-100、
  至少一题、总分 100、题干/选项/答案完整、至少一名员工的发布校验
- 发布坞展示具体校验失败原因,不再静默禁用按钮
- CHANGELOG/README 同步 2026-07-25 组织姓名定向补齐与生产复核记录
2026-07-25 18:15:32 +08:00
admin acd5fd3a6d fix(practice): generate replies from coach hints 2026-07-25 15:44:45 +08:00
admin 230dfb4dfc feat(broadcast): finish multi-role insight experience 2026-07-25 15:18:58 +08:00
admin 2b3c37677d fix(mobile): prioritize practice actions above guidance 2026-07-25 13:17:32 +08:00
admin fa9d6da975 feat(practice): streamline pilot content operations 2026-07-25 12:51:39 +08:00
admin 35b37b07f7 feat(practice): server-owned realtime personas with knowledge tool calling
- AihrRealtimePersonaRegistry whitelist: owner-calm (default), owner-impatient,
  digital-mentor (search_knowledge); persona binds default voice
- /realtime/session assembles session.update server-side (instructions/tools);
  browser forwards payload verbatim; Redis session record 30min with sliding renewal
- /realtime/tools/invoke validates login identity + Redis session ownership +
  persona tool whitelist, then read-only searchAuthorized; per-account rate limits
- source=realtime skips sop review and knowledge-gap persistence (Beta no-persist)
- frontend: persona cards replace 56-voice picker; serialized tool-call chain with
  soft-landing fallback
2026-07-25 11:13:04 +08:00
admin 3a19b475a8 feat(mobile): add voice-to-text input to direct feedback page
- 反馈内容 label 行新增语音 chip:toggle 录音(启动/录音计时/结束中/转写
  四态),转写结果以换行追加,JS 侧截断至 5000 字上限并提示
- 复用既有 services/speech.ts + /api/ai/asr 链路;表单页文字为主路径,
  录音不可用或权限失败仅提示改文字输入,不做选文件降级
- voiceStopping 状态修复 stop→onCapture 竞态(重复点按不再丢录音)
- onHide/onUnload 统一 teardownVoice:generation++、abort 转写、
  cancel 录音、停计时,切页无迟来写回
- 渠道按钮加图标(vip/wallet/staff/eye/gear),匿名行与空历史态补图标
- 测试改用函数体提取断言,覆盖清理/竞态/截断/模板契约;150/150
  单测、vue-tsc、H5 构建通过,mock API 浏览器验证通过

已经过 Codex 审查
2026-07-25 03:00:30 +08:00
admin f545983de8 fix(knowledge): bind summary cards to cited evidence 2026-07-25 01:45:41 +08:00
admin 4d2b3828c0 feat(brand): rename product to 帮道 2026-07-25 01:09:49 +08:00
admin c9d2012ec1 feat(aihr): finalize practice growth and access boundaries 2026-07-25 00:42:19 +08:00
admin f6ffafda30 fix(mobile): type direct feedback switch event 2026-07-25 00:16:56 +08:00
admin 09278d40c6 merge: integrate broadcast question correction
# Conflicts:
#	docs/BRD_PRODUCTION_MIGRATION_RUNBOOK.md
2026-07-25 00:13:49 +08:00
admin 5f8d8f96f0 fix(agent): preserve broadcast consultation context 2026-07-25 00:12:53 +08:00