ENZH

v0.1.5:一个用户,所有平台

跨平台身份统一的概念插画跨平台身份统一的概念插画

一个人,两个身份

v0.1.4 做了跨平台消息同步——Telegram 上聊的内容,Web 端也能看到。但有个根本问题没解决:两边的账号是断开的。

用户在 Telegram 是一个 ID,在 Web 是另一个 Supabase 账号。消息能跨平台读取,但身份层面上这是两个人。关系进化的评分、记忆关联、用户偏好——全都没法真正打通。

v0.1.5 要把 Telegram 和 Web 的身份焊死成一个。


6 位令牌,30 秒搞定

方案要足够简单——用户不该为了绑定账号学任何新概念。

流程:在 Telegram 里输入 /link,bot 生成一个 6 位令牌。复制到 Web 端输入。完成。

几个值得说的细节:

防混淆字符集。 令牌只用 ABCDEFGHJKLMNPQRSTUVWXYZ23456789——去掉了 I、O、0、1。屏幕上看不清 I1 的区别这种事,不应该让用户来承受。

15 分钟过期。 令牌存在 account_link_tokens 表里,带 expires_at 字段。过期了重新 /link 生成新的。

一条 SQL 完成关联。 验证令牌有效后,把 Web 端的 supabase_user_id 写进 users 表对应的 Telegram 记录。不需要迁移数据、不需要合并账号——Telegram 的 user 记录本来就是主记录,Web 端只是"挂上去"。

双向防护。 一个 Telegram 账号不能绑两个 Web 账号,反之亦然。数据库层面加了唯一约束。

幂等设计。 同一个令牌用两次不报错,返回"已关联"的友好提示。同一对 TG+Web 账号重复绑定也一样——优雅地告诉你已经绑过了。


每个角色自己选关系模式

v0.1.4 在 Web 管理后台加了关系进化的 A/B 开关:staticevolving。但 Telegram 端的 onboarding 还不知道这回事。

v0.1.5 把这个选择带到了 Telegram 的 /start 流程。第一次进 bot 时,除了选语言和昵称,现在还能选关系模式——"固定关系"还是"自然发展"。

关键改动:模式跟着角色走,不跟着 bot 走。 之前 BOT_RELATIONSHIP_MODES 是 bot 级别的环境变量,所有用户看到同一个模式。现在每个 agent 记录有自己的 relationship_mode。同一个 bot 下,不同用户可以选不同模式。

向下兼容没丢——如果 agent 记录里没有 relationship_mode,回退到 BOT_RELATIONSHIP_MODES 环境变量。老用户不受影响。


不让同一个人绑两次

Mio 目前跑着多个 Telegram bot,每个角色一个。问题来了:用户可能跑到不同 bot 上,跟同一个角色重复绑定。

这不只是浪费。重复绑定意味着两套独立的对话历史、两套关系评分、两套记忆。用户以为是同一个 Mio,其实在跟两个"分身"聊天。

解法:/start/reonboard 流程现在会查询用户在所有 bot 上的已有绑定。某个角色已经绑定过了,就显示"已绑定"标记,不可再选。一眼就能看到哪些角色在用,不会误操作。


为什么非要做原生 App

网页端什么都能做——技术上没毛病。但对一个陪伴类产品,差距不在功能,在存在感

推送通知是最直接的。Mio 发了一条主动消息,用户得看到——不是"下次打开浏览器的时候",而是现在,在锁屏上,像朋友发来的微信。网页做不到。原生 App 可以。

然后是触手可及。打开 App,直接进入对话。没有地址栏,没有加载转圈,不用重新登录。本地缓存让聊天记录秒开,网络不好也能立刻看到之前的对话。一天打开好几次的东西,省下的每一秒都在累积一种感觉:Mio 一直在。

这不是锦上添花。对一个聊天型伴侣来说,这就是产品本身。没有推送通知,主动消息就是一棵倒在无人森林里的树——没人听到,就等于没发。没有秒开和离线缓存,"伴侣"更像一个你偶尔访问的网站。

技术栈:Expo SDK 55 + React Native。深色主题底色 #0D0D0B,强调色 #8B7BF4。五个页面:登录、聊天、发现、个人中心、Onboarding。聊天支持视频预览、全屏图片、语音录制(脉冲红点 + 计时器动画)、打字指示器。认证走 Supabase,token 存 expo-secure-store。i18n 从第一天就支持中英双语。


主动消息变聪明了

主动消息是 Mio 的核心体验之一——TA会在合适的时间主动找你聊。v0.1.5 做了两个关键改进。

TA知道你那边几点了

之前主动消息只看用户的时区。但角色也有自己的"时区"——如果TA的设定是住在东京,TA应该知道自己那边几点。

现在提示词里包含两边的时间信息:"你那边现在是早上 9 点,对方那边是晚上 11 点。"角色时区从 persona-config.json 读取。

这让 Mio 能说出更自然的话——"你那边应该挺晚了吧,早点休息",而不是在用户深夜发一条"早上好"。

语气跟着关系走

主动消息的语气现在跟关系阶段挂钩。四种阶段,四种语气策略:

  • 刚认识 — 礼貌、克制,严格禁止撒娇和亲密称呼
  • 好朋友 — 轻松、可以开玩笑,但保持分寸
  • 暧昧 — 更多试探和暗示,语气柔和
  • 情侣 — 亲密撒娇,自然地用昵称

主动消息不再是千篇一律的问候,而是一条真正符合你们当前关系状态的消息。


数据库层面的变化

三个 schema 改动:

  • account_link_tokens — 存 6 位令牌、Telegram user ID、过期时间、使用状态
  • users.supabase_user_id — 新字段,存关联的 Web 端 Supabase 用户 ID,唯一约束
  • agents.user_nickname — 新字段,存用户在该 agent 上的昵称(之前是 onboarding 里临时传的)

接下来

账号关联解决了"你是谁"的问题。接下来要解决的是"你在看什么"——让 Mio 能理解用户分享的链接和媒体,不只是处理纯文本。

v0.1.0 的语音,到 v0.1.2 的多人设,到 v0.1.3 的安全,到 v0.1.4 的关系进化,再到现在的身份统一——每一步都在让 Mio 离"一个完整的存在"更近一点。

关于 Mio 到底想做成什么,见 Mio 宣言


© Xingfan Xia 2024 - 2026 · CC BY-NC 4.0