Anna App: Mini Notes with LLM Summary — 完整项目规划
生成日期:2026-07-03
状态:规划阶段,尚未开始编码
这是一个 Anna App 平台本地开发能力验证项目 ,不是普通 Web App。核心目标是证明你理解 Anna App 的平台模型:
Anna App iframe(前端)
→ AnnaAppRuntime.connect() // 连接 Host
→ anna.storage.* // 通过 Host API 读写存储
→ anna.tools.invoke(...) // 通过 Host API 调用本地工具
→ 本地 Executa Tool(JSON-RPC/stdio) // 工具进程
→ sampling/createMessage // 工具反向请求 Host LLM
→ Summary 返回 UI // 结果回传前端
约束
说明
不能绕过 Anna 平台模型
不直接调 localStorage/HTTP API/llm.complete
必须走 Executa Tool
总结必须通过 anna.tools.invoke → Executa → sampling → Host LLM
必须是工程化前端
源码目录 + 构建脚本,不能是单文件 HTML
必须可本地复现
anna-app dev --no-llm + anna-app executa dev --mock-sampling
必须能三平台打包
darwin-arm64/x86_64 + windows-x86_64 binary
审阅者 :会按 README 步骤逐步验收
你自己 :需要本地开发、调试、测试
用户打开 Anna App,看到笔记列表(可能为空)
用户输入文字,点击保存 → 笔记存入 anna.storage
用户点击删除 → 笔记从 anna.storage 移除
用户点击 Summarize → 前端调 anna.tools.invoke → Executa Tool → sampling → LLM 总结 → UI 展示
编号
功能
验收方式
M1
创建笔记
输入文字 → 保存 → anna.storage.set 调用可追踪
M2
笔记列表
从 anna.storage.get 读取并展示
M3
删除笔记
删除 → anna.storage.set 更新存储
M4
LLM 总结
Summarize 按钮 → anna.tools.invoke → Executa → sampling
M5
空状态
无笔记时显示引导文案
M6
错误状态
--no-llm 下 Summarize 显示 [-32603] 错误
M7
manifest.json
完整声明 schema/executas/permissions/ui/dev
M8
Executa Tool
JSON-RPC/stdio, initialize/describe/invoke/health/shutdown
M9
Mock sampling fixture
.jsonl 文件用于 --mock-sampling
M10
前端构建
npm run build 生成可加载 bundle
M11
二进制打包
三平台 binary archive
M12
GitHub Actions
release workflow 三平台构建 + smoke test
M13
README
完整说明
功能
原因
笔记编辑
题目明确不要求
搜索/标签/分类
题目明确不要求
多笔记本
题目明确不要求
富文本/附件
题目明确不要求
协同编辑
题目明确不要求
复杂 UI 美化
题目明确不要求
真实 LLM API 集成
题目明确不要求
云端 APS 存储
题目明确不要求
时间戳显示
可选,MVP 可先不做
加载动画
锦上添花,MVP 后加
Mini Notes App
├── 1. 前端 UI(React + TypeScript + Vite)
│ ├── 1.1 AnnaAppRuntime 连接层(connect/disconnect/error)
│ ├── 1.2 Storage 服务层(get/set 封装)
│ ├── 1.3 Tools 服务层(invoke 封装)
│ ├── 1.4 笔记列表组件(列表/空状态/错误状态)
│ ├── 1.5 创建笔记组件(输入框/验证/提交)
│ ├── 1.6 删除笔记组件(确认/执行)
│ └── 1.7 总结组件(按钮/结果展示/错误展示)
│
├── 2. Executa Tool(Node.js/TypeScript → 打包为 binary)
│ ├── 2.1 JSON-RPC 2.0 over stdio 服务器
│ ├── 2.2 initialize(capability negotiation v2)
│ ├── 2.3 describe(返回 tool manifest)
│ ├── 2.4 invoke(summarize handler → sampling)
│ ├── 2.5 health(健康检查)
│ ├── 2.6 shutdown(优雅退出)
│ └── 2.7 日志系统(stderr)
│
├── 3. 配置与元数据
│ ├── 3.1 manifest.json(Anna App 清单)
│ ├── 3.2 executa/executa.json(Executa 清单)
│ └── 3.3 package.json(前端 + 根 workspace)
│
├── 4. 测试与 Mock
│ ├── 4.1 mock-sampling fixture(.jsonl)
│ └── 4.2 手动测试脚本
│
├── 5. 构建与打包
│ ├── 5.1 前端构建脚本(Vite → dist/)
│ ├── 5.2 Executa binary 打包脚本
│ └── 5.3 GitHub Actions release workflow
│
└── 6. 文档
└── 6.1 README.md
层次
技术选型
理由
前端框架
React 18 + TypeScript
生态成熟,类型安全
构建工具
Vite
快速构建,Anna App 友好
包管理
pnpm
monorepo 支持好
Executa Tool
Node.js + TypeScript
与前端统一语言,降低心智负担
Binary 打包
pkg / bun build / sea
将 Node.js 打包为独立二进制
JSON-RPC
手写轻量实现
依赖少,协议简单,可控制
CI/CD
GitHub Actions
题目要求
Lint
ESLint + Prettier
代码质量
虽然题目不限语言,但推荐 Node.js/TypeScript 因为:
与前端统一语言,减少上下文切换
可用 pkg(by Vercel)或 bun build --compile 打包为三平台二进制
JSON-RPC 处理已有成熟库可参考
备选方案:Go(天然跨平台编译,单 binary,但需要学两套语言);Python(生态好但 binary 打包重)。
mini-notes-app/
├── manifest.json # Anna App 根清单
├── package.json # workspace root
├── pnpm-workspace.yaml # pnpm monorepo 配置
├── README.md # 完整说明文档
│
├── ui/ # 前端项目
│ ├── package.json
│ ├── vite.config.ts
│ ├── tsconfig.json
│ ├── index.html
│ └── src/
│ ├── main.tsx # 入口:挂载 React + 连接 Anna
│ ├── App.tsx # 根组件
│ ├── anna/ # Anna Runtime 连接层
│ │ ├── runtime.ts # AnnaAppRuntime.connect() 封装
│ │ ├── storage.ts # anna.storage.get/set 封装
│ │ └── tools.ts # anna.tools.invoke 封装
│ ├── components/ # UI 组件
│ │ ├── NoteList.tsx # 笔记列表
│ │ ├── NoteItem.tsx # 单条笔记
│ │ ├── NoteInput.tsx # 创建笔记输入
│ │ ├── Summarize.tsx # 总结按钮与结果
│ │ ├── EmptyState.tsx # 空状态
│ │ └── ErrorBanner.tsx # 错误提示
│ ├── hooks/ # 自定义 Hook
│ │ └── useNotes.ts # 笔记 CRUD 状态管理
│ └── types.ts # TypeScript 类型定义
│
├── executa/ # Executa Tool
│ ├── executa.json # Executa manifest
│ ├── package.json
│ ├── tsconfig.json
│ └── src/
│ ├── index.ts # 入口:stdio 循环
│ ├── rpc.ts # JSON-RPC 2.0 实现
│ ├── handlers/ # 方法处理器
│ │ ├── initialize.ts # v2 capability negotiation
│ │ ├── describe.ts # 返回 manifest
│ │ ├── invoke.ts # summarize handler
│ │ ├── health.ts # 健康检查
│ │ └── shutdown.ts # 优雅退出
│ └── types.ts # 类型定义
│
├── fixtures/ # 测试 fixture
│ └── sampling-mock.jsonl # --mock-sampling fixture
│
├── scripts/ # 工具脚本
│ ├── build-executa.sh # 本机二进制打包
│ ├── test-rpc.sh # 手动 JSON-RPC 测试
│ └── build-executa.ps1 # Windows 打包脚本
│
└── .github/
└── workflows/
└── release.yml # GitHub Actions release workflow
步骤
任务
产出
1.1
初始化 monorepo(pnpm workspace)
根 package.json, pnpm-workspace.yaml
1.2
创建 manifest.json(Anna App 清单)
manifest.json
1.3
初始化前端项目(React + Vite + TS)
ui/ 目录, 可构建
1.4
初始化 Executa Tool 项目(Node.js + TS)
executa/ 目录
阶段 2:Executa Tool 核心(预计 3-4 小时)
步骤
任务
产出
2.1
实现 JSON-RPC 2.0 over stdio 框架
读 stdin → 路由 → 写 stdout
2.2
实现 initialize handler
v2 capability negotiation
2.3
实现 describe handler
返回 tool manifest
2.4
实现 health + shutdown handler
基础运维
2.5
实现 invoke handler(summarize)
构建 sampling 请求
2.6
实现 sampling/createMessage 反向请求
reverse JSON-RPC
2.7
手动测试 initialize/describe/invoke
验证 stdio 通信
步骤
任务
产出
3.1
实现 AnnaAppRuntime 连接层
runtime.ts
3.2
实现 anna.storage.* 封装
storage.ts
3.3
实现 anna.tools.invoke 封装
tools.ts
3.4
实现创建笔记(UI + storage.set)
NoteInput.tsx
3.5
实现笔记列表(storage.get + 展示)
NoteList.tsx, NoteItem.tsx
3.6
实现删除笔记(storage.set 更新)
NoteItem 删除按钮
3.7
实现空状态 + 错误状态
EmptyState, ErrorBanner
3.8
实现 Summarize(tools.invoke + 结果展示)
Summarize.tsx
3.9
配置 Vite 构建为 Anna App bundle
vite.config.ts
阶段 4:Mock Sampling Fixture(预计 0.5 小时)
| 4.1 | 创建 sampling-mock.jsonl | fixtures/ 目录 |
步骤
任务
产出
5.1
anna-app validate --strict
通过校验
5.2
anna-app dev --no-llm UI 测试
创建/查看/删除正常
5.3
anna-app executa dev --mock-sampling
sampling 路径验证
5.4
手动 JSON-RPC 测试
脚本或说明
步骤
任务
产出
6.1
编写本机二进制打包脚本
scripts/build-executa.sh
6.2
验证 archive 结构
manifest + binary
6.3
编写 GitHub Actions workflow
.github/workflows/release.yml
6.4
测试 release workflow
三平台 assets
| 7.1 | 编写 README.md | 覆盖所有验收标准 |
(详见 TASKS.md ,此处为概览)
阶段
名称
状态
预计时间
1
项目骨架
⬜ Pending
1-2h
2
Executa Tool 核心
⬜ Pending
3-4h
3
前端核心
⬜ Pending
3-4h
4
Mock Fixture
⬜ Pending
0.5h
5
集成测试
⬜ Pending
1-2h
6
打包与发布
⬜ Pending
2-3h
7
文档
⬜ Pending
1-2h
总预计时间:12-18 小时
┌──────────────────────────────────────┐
│ Mini Notes [icon] │ ← 标题栏
├──────────────────────────────────────┤
│ ┌──────────────────────────────┐ │
│ │ 输入你的笔记... │ │ ← 输入框
│ └──────────────────────────────┘ │
│ [保存] [✨ Summarize 全部笔记] │ ← 操作按钮
├──────────────────────────────────────┤
│ 笔记列表 (3) │ ← 列表标题
│ ┌──────────────────────────────┐ │
│ │ 1. 明天跟客户 follow up [✕] │ │ ← 笔记项
│ │ 2. 修复登录 bug [✕] │ │
│ │ 3. Workshop 内容想法 [✕] │ │
│ └──────────────────────────────┘ │
├──────────────────────────────────────┤
│ 📝 Summary │ ← 总结区(初始隐藏)
│ 你记录了 3 条笔记,主要涉及... │
└──────────────────────────────────────┘
品牌/标题 → 用户知道这是什么 App
输入区 → 主要操作入口
笔记列表 → 核心内容
总结区 → 增强功能
组件
正常态
空状态
加载态
错误态
禁用态
NoteInput
可输入
—
保存中...
保存失败提示
空内容时保存按钮禁用
NoteList
展示笔记
"还没有笔记,写一条吧"
加载中...
"加载失败,请重试"
—
NoteItem
内容 + 删除按钮
—
删除中...
删除失败提示
—
Summarize
按钮可点击
"没有笔记可总结"
"正在总结..."
[-32603] 错误
—
保存后清空输入框 ,光标回到输入框
删除不需要确认弹窗 (笔记很短,误删代价低),但可以做 1 秒的撤销 toast
Summarize 按钮 在没有笔记时禁用
错误信息 使用红色/橙色文字,不是 alert 弹窗
品牌色 :选一个主色(如 indigo-600),统一按钮、链接、图标
圆角 :卡片 8px,按钮 6px,输入框 6px
阴影 :列表卡片加轻微阴影 shadow-sm
间距 :统一使用 4px 倍数(4/8/12/16/24/32)
字体 :系统字体栈,标题稍大(16px),正文 14px
图标 :使用简单的 emoji 或 SVG icon
hover 效果 :按钮 hover 变色,列表项 hover 加背景色
过渡动画 :删除时 200ms fade out
资料
作用
来源
Anna App 开发文档
理解 Host API、storage、tools
staging.anna.partners/developers
示例仓库源码
Executa Tool 写法参考
github.com/whtcjdtc2007/anna-executa-examples
MCP Sampling 规范
理解 sampling/createMessage
modelcontextprotocol.io
@anna-ai/app-runtime README
SDK API 参考
npm
@anna-ai/cli README
CLI 命令参考
npm
Executa binary distribution 文档
打包规范
staging.anna.partners/developers
Anna App 知识库
├── 1. 平台概念 ← Anna App 是什么,Host API 模型
├── 2. Storage API ← anna.storage.get/set 用法
├── 3. Tools API ← anna.tools.invoke 用法
├── 4. Executa Tool ← JSON-RPC/stdio/manifest/sampling
├── 5. MCP Sampling ← sampling/createMessage 协议细节
├── 6. CLI 命令 ← anna-app dev/validate/executa
├── 7. 二进制分发 ← 打包结构/platform key/archive 格式
└── 8. 示例代码 ← 参考仓库中的最佳实践
anna.storage.get 和 anna.storage.set 的完整签名和返回值格式是什么?
anna.tools.invoke 的 tool_id 应该从哪里来?如何与 manifest 对应?
Executa Tool 的 describe 返回的 manifest 完整结构是什么?
sampling/createMessage 请求的完整字段有哪些?哪些是必须的?
anna-app dev --no-llm 和 anna-app executa dev --mock-sampling 的区别是什么?
二进制 archive 的根目录 manifest.json 应该包含哪些字段?
required_executas 和 ui.host_api.tools 如何保持一致?
每个回答标注来源文档章节
不确定的 API 行为先在本地用 anna-app dev 验证
示例代码必须能在本地跑通再写入项目
Skill 名称
触发场景
价值
anna-app-init
初始化 Anna App 项目
一键生成骨架
anna-app-validate
提交前校验
自动跑 validate --strict
executa-dev
开发 Executa Tool
自动启动 dev + mock sampling
executa-build
打包二进制
自动识别平台打包
release-anna-app
发布 GitHub Release
三平台构建 + 上传
10.2 推荐的第一个 Skill:anna-app-init
这是最有复用价值的 Skill,每次新建 Anna App 都要做同样的事。
---
name : anna-app-init
description : 初始化一个 Anna App 项目骨架,包括 manifest.json、前端项目、Executa Tool 项目
---
# Anna App Init Skill
## 触发条件
用户说"创建 Anna App 项目"/"初始化 Anna App"/"new anna app"
## 执行步骤
1 . 询问用户 App 名称和基本描述
2 . 创建目录结构(manifest.json, ui/, executa/, fixtures/, scripts/, .github/)
3 . 生成 manifest.json(含 schema, required_executas, permissions, ui, dev)
4 . 初始化前端项目(Vite + React + TypeScript)
5 . 初始化 Executa Tool 项目(Node.js + TypeScript + JSON-RPC 骨架)
6 . 创建 mock sampling fixture 模板
7 . 创建 README 模板
8 . 运行 ` pnpm install `
## 输出
- 完整的项目骨架
- 可立即 ` anna-app dev --no-llm ` 启动
- 可立即 ` anna-app validate --strict ` 通过
维度
评价
最认可
核心链路清晰:创建→存储→总结,功能范围控制得好
最大问题
缺少"撤销删除"的用户体验考量,虽然题目不要求
修改建议
Summarize 按钮建议放在列表上方而非底部,方便用户随时看到
优先改一处
输入框应支持 Enter 键提交,降低操作成本
维度
评价
最认可
分层清晰(runtime/storage/tools → components → hooks)
最大问题
AnnaAppRuntime 连接是异步的,组件需要处理"连接中"状态
修改建议
用 React Context 包裹 anna 实例,避免 prop drilling
优先改一处
确保 Vite 构建产物是纯静态文件,manifest.json 的 ui.bundle.entry 指向正确的入口
维度
评价
最认可
Executa Tool 的 JSON-RPC/stdio 设计遵循标准协议
最大问题
stdin 逐行读取可能遇到多行 JSON(pretty-print),需处理
修改建议
使用 readline + JSON.parse 逐行解析,而不是简单的 split
优先改一处
stdout flush 必须在每次响应后立即执行,否则 host 会卡住
维度
评价
最认可
sampling 链路完整,从 tool invoke 到 createMessage 到响应
最大问题
prompt 设计直接影响总结质量,目前没看到 prompt 模板
修改建议
在 invoke handler 中设计 prompt 模板:"请用中文总结以下笔记:\n{notes}"
优先改一处
sampling/createMessage 的 maxTokens 应设为合理值(如 500),避免浪费
维度
评价
最认可
功能简单直接,没有学习成本
最大问题
删除按钮太小容易误触,且没有撤销
修改建议
删除按钮放在笔记右侧,用灰色 ✕ 图标,hover 变红
优先改一处
输入框 placeholder 改成更友好的文案:"写点什么..."
维度
评价
最认可
验收标准覆盖全面,README 要求详尽
最大问题
README 需要解释每个命令的"为什么",不只是"怎么做"
修改建议
在 README 中加入一段"Anna App 平台模型解释",展示关键链路
优先改一处
manifest.json 的字段必须有注释或 README 解释其含义
维度
评价
最认可
monorepo 结构合理,前端/Tool 分离清晰
最大问题
binary 打包选型未确定——pkg 已停止维护,bun build 不够成熟
修改建议
推荐使用 Node.js SEA (Single Executable Applications) 或改用 Go 实现 Executa
优先改一处
先确定 binary 打包方案并验证,这是最大风险点
风险
等级
影响
缓解措施
Binary 打包方案不可行
🔴 高
无法交付三平台二进制
优先验证,备选 Go 重写
Anna App SDK 版本不兼容
🟡 中
API 行为与预期不同
写死 SDK 版本号,README 注明
stdin/stdout 通信问题
🟡 中
Executa 不响应或响应乱序
充分测试 readline + flush
sampling 协议理解偏差
🟡 中
sampling 请求格式错误
参考 MCP 规范 + 示例仓库
GitHub Actions 权限问题
🟢 低
release 上传失败
使用标准 action,提前测试
Vite 构建产物不兼容
🟢 低
bundle 无法被 Anna App 加载
确保是纯静态文件,相对路径
#
标准
通过条件
1
安装依赖
pnpm install 无报错
2
构建前端
pnpm build 生成 ui/dist/
3
manifest 校验
anna-app validate --strict 通过
4
UI harness
anna-app dev --no-llm 可访问
5
创建笔记
输入文字→保存→anna.storage.set 被调用
6
查看笔记
列表展示→anna.storage.get 被调用
7
删除笔记
点击删除→列表更新→anna.storage.set 被调用
8
Summarize(--no-llm)
点击→anna.tools.invoke 被调用→显示 [-32603] 错误
9
Executa sampling
anna-app executa dev --mock-sampling fixture.jsonl 通过
10
sampling 证据
fixture/log 确认 sampling/createMessage 被发起
11
手动 RPC 测试
initialize/describe/invoke 均正常响应
12
二进制打包
本机脚本生成 archive,结构符合规范
13
GitHub Release
workflow 触发→三平台 assets→smoke test 通过
14
README
覆盖所有要求主题
阅读 Anna 开发者文档和示例仓库 (2-3 小时)
理解 Host API 的完整签名
理解 Executa Tool 的 manifest 格式
理解 binary distribution 的 archive 结构
跑通示例仓库中的至少一个 Executa Tool
初始化项目骨架 (30 分钟)
mkdir mini-notes-app && cd mini-notes-app
创建 manifest.json
pnpm init + 配置 workspace
pnpm create vite ui --template react-ts
创建 executa/ 目录
验证骨架可用 (30 分钟)
写一个最小可用的前端(只展示 "Hello Anna")
写一个最小 Executa Tool(只实现 initialize + describe)
anna-app validate --strict 确认骨架正确
anna-app dev --no-llm 确认能加载
然后按照「六、开发步骤」阶段 1 → 2 → 3... 推进
⚠️ 重要提醒 :先跑通"最小骨架可加载"再开始写业务代码。如果骨架都加载不了,后面都是白费。
本文档将随项目进展持续更新。下一步:创建 PROJECT.md、PLAN.md、TASKS.md 等管理文件。