wangzan101/Mika 是昨天才建库的安卓 AI 助理。它最不像玩具的地方,不是能调用大模型, 而是它把「像人一样用手机」拆成了一组可以测的数字:落指前停多久、按住多久、手势偏几像素、 两次对外动作之间隔几秒。这篇文章把它的源码拆开看。
仓库 2026-10-29 14:34 UTC 建立,现在是 105 ★ / 20 fork / 1 个 open issue。 全部提交来自同一个人,共 13 次。这三个数字放在一起,本身就是一个结论:这是一个人用 AI 辅助、两天里压出来的完整产品级代码库。 值得讨论的不是「是不是 AI 写的」,而是「这样写出来的东西,到底站不站得住」。
Mika 的能力不是一个大循环,而是三层互不认识的模块。这个划分贯穿整个仓库,也是它能被单测覆盖的前提。
最值得看的是依赖方向::core 是纯 Kotlin(不依赖安卓),:app 是安卓宿主;
core/cap/<能力> 依赖核心,核心不引用任何能力,能力之间也互不引用,只有装配层同时认识几种能力。
这条规则由一个叫 PackageDependencyTest 的测试守着——不是写在文档里,是写进 CI 之外的构建里。
docs/architecture.md §1
全仓库最不像「AI 生成」的地方,是 GesturePacing.kt 和 OutwardPacing.kt 这两个文件。
它们不优化速度,专门负责变慢——因为一个 0 毫秒落指、匀速直线滑动的操作,在任何风控系统眼里都不是人。
还有一套按网站算的:同一站点连续换页,第一页不停,第二页起停 4–7 秒,每多一页上下限各加 0.6 / 1 秒,最长 12 秒;标了 pace: careful 的站点从 10–16 秒起,最长 30 秒。同一个站一个任务最多 20 页(careful 12 页),到了就让模型停下来问你。
所有改变外部世界的动作——点一下、打一个字、发一条消息、跑一条命令——都必须经过 ActionExecutor。
这不是约定,是编译期强制:ToolDispatcher.execute 要一个 ActionPass,而它的构造函数是 internal,只有 ActionExecutor 能造。
treeBlind,不说「多半没点上」。Redactor 遮掉。
复合工具(一次多步的 do_steps、沙箱里的 mika phone、网页脚本)内部的每个子动作,经 SubActions 回到同一个入口——所以「批量打招呼」和「点一个按钮」走的是同一条记录路径,也受同一套节奏约束。
docs/architecture.md §4 · core/action/ActionExecutor.kt
18 个 App 的 APP.md、12 个网站的 SITE.md、4 个技能,加起来只有 54 KB。
格式是带 YAML 头的 Markdown,加一份就是加一个目录。构建时 KnowledgeIndex 扫头部、校验、生成索引,校验不过直接构建失败。
这份东西的护城河不在代码里,在内容里——写微信的坑、写小红书的入口,比写一行 Kotlin 难得多。
prompts/ 有 464 KB,分 P0 身份 / P1 准则 / P2 能力段 / P3 工具说明 / 入口短说明 / 反馈文案。
规则很硬:system/ 里不许出现任何工具名(由测试检查);工具结果文案必须自成一体,代码不许用 + 拼;
每条反馈键都要有代码在用。全部文字有金样测试,四种工具展开情形的全貌和字节数都存在 prompt-surface/ 里——改一个字的后果会出现在提交差异里。
输入估算超过上下文的 0.6 才压缩,压到触发线一半以下;用户说的话永不裁剪,压缩后 ContextRecovery 把缺了的原话补回原位。
这是全仓库最有争议的一个决定。它只在一件事上停你:钱。
| 动作 | 询问模式(默认) |
|---|---|
| 下单、付款、屏上有金额时的提交 | 停,出确认卡片(只同意这一次 / 不同意) |
| 发消息、发帖、提交表单 | 直接做 |
| 删除、改账号或安全设置 | 直接做 |
| 往密码框里打字 | 直接做 |
| 看不出是什么的按钮 | 直接做 |
| 定时任务 / 子任务 / MCP(无人在场) | 付款一律拒绝,别的照做 |
作者的理由写在提交信息里:「发消息不算花钱」——商家客服、闲聊里提到价钱不该被拦。代价是,误发、误删的锅是用户的。 开发者选项里有个「自主模式」,开了连付款也不问。而 roadmap 自己承认了一处漏洞:自主模式的提前返回排在「不操作 Mika 自己」的检查之前,所以那层保护在自主下不生效。
value 选元素只拦了直接写的选择器,CSS 转义还能绕;②秘密输入框只遮了 value,valueAsNumber / selectionStart 还能间接读出内容;③fetch 请求头全放行,没做白名单;④「是不是密码框」只看只读环境建立之后的变化。./gradlew updateReadme 从源码重新生成,还有测试守着两边一致。DocsConsistencyTest 读仓库根目录的文档,再对照 app 源码——文档过期会挂测试。eval/tasks/ 分了 barrier / impossible / irreversible / memory / read / skills / web / write,不可逆题默认不跑,要显式开。.github/ 都没有。所有测试都是本地跑的,没有一道门拦着。TaskRun.reviewFinalAnswer = false,所以回答一律记为「未核实」,而技能草稿、经验回放都要求「核实过」——整个学习闭环目前是死的。docs/roadmap.md「已知问题」第 1 条
一句话:这是「技术含量远大于商业可行性」的那类项目。它不解决「普通人怎么用上 AI」, 它解决的是「一个 agent 怎么才敢替你在真手机上按下那个按钮」——而这个问题,大多数做移动 agent 的团队都还没开始认真回答。
想玩可以下 APK:安卓 11 能装,13 才能跑任务,14 体验最好;沙箱只支持 arm64。 但别拿主微信试。
docs/architecture.md(265 行,按代码现状写,带类名与文件路径)docs/roadmap.md(已完成 / 接下来 / 已知问题与暂缓)docs/knowledge-format.md文中所有数字来自本地克隆的源码与文档,非二手转述。