Skip to content

feat(26.5.12v1 + 26.5.13v1): P1 产品价值收官 (6 子项) + 飞书 UX 全面升级 (F1)#31

Merged
cursor[bot] merged 14 commits into
mainfrom
cursor/-bc-a08559c2-6ba9-46d4-837c-755710698303-9cc8
May 16, 2026
Merged

feat(26.5.12v1 + 26.5.13v1): P1 产品价值收官 (6 子项) + 飞书 UX 全面升级 (F1)#31
cursor[bot] merged 14 commits into
mainfrom
cursor/-bc-a08559c2-6ba9-46d4-837c-755710698303-9cc8

Conversation

@Zyling-ai
Copy link
Copy Markdown
Owner

@Zyling-ai Zyling-ai commented May 12, 2026

两个 release 一并交付

[26.5.12v1] — 第 4 程:产品价值收官(6 子项)

把 README 顶层 "P1 规划中" 清单一口气全做掉。

# 子项 Commit
1 B-05 Web 访客升级为命名联系人 ed29a95
2 E-01 头像 API 拉取 + 本地缓存(飞书/TG) 4e12206
3 GoalsChat sidebar 状态注入 AI context 6269a58
4 B-03 跨 agent 联系人/群聊聚合视图 32b43ce
5 F-03 工具调用全量审计 + ToolAuditView cae430d
6 F-01 工具审批 policy=ask 端到端 af29ec1
Δ 端到端 SSE 审批流测试 6df4a01
Δ 9 个深度测试(race / 多字节 / audit) 9ceb766

51 个新单测 -race 全绿,端到端 smoke 通过。

[26.5.13v1] — 飞书集成 UX 全面升级 (F1)

把"给 agent 绑定飞书机器人"从 10 步摸黑配置变成 30 秒可视化向导。

子项 Commit
F1-backend:pkg/channel/feishu_probe.go 一站式 probe + 9 单测 b3f56bd
F1-frontend:FeishuSetupWizard.vue 4 步向导 + deep links + auto-fix 430e1cf
F1-status:channel card live 「🪶 飞书状态」可展开 panel c1aca9b
release notes + binaries 58dac7e

关键功能

  • POST /api/feishu/probe:一次调用并发完成验证凭据 + 拉 bot 身份 + 检测 5 个 OAuth scope + 检测 im.message.receive_v1 订阅 + 长连接状态 + 列已加群
  • 4 步向导:(1) 配置清单 + 跳转飞书后台 (2) 一键绑定显示 bot 头像/名字 (3) 缺权限/事件深链 open.feishu.cn/app/{appId}/{auth,event,version} + 复制权限名 + 重新检测 (4) 启动测试 + 加群预览
  • 错误从「测试失败」变精确文案:「App Secret 错了」/「应用还没上线」/「还缺 X 权限点」
  • AgentDetailView 渠道卡片新增「🪶 飞书状态」可展开块(bot 头像 + 已加群 + 问题诊断)
  • 引入 larksuite/oapi-sdk-go v3.7.5(+3 MB)为后续 F2 铺路

调研结论

  • 砍 lark-cli 集成(违反零配置定位)
  • 砍 lark-openapi-mcp(同理 + Beta)
  • F2 全面 SDK 化(替换手撸 WS/protobuf 1800 行)+ F4 群聊看板写操作 → 推迟到独立后续 PR

累计指标

  • 14 个 commits(含 release 2 个)
  • 60 个新单测 全部 -race -count=1 绿
  • go test ./... 27 个包全绿
  • cd ui && npm run build 通过
  • 预编译二进制刷新 @ 26.5.13v1(zyhive-{linux-amd64,darwin-arm64})
  • 端到端 smoke 测试:所有新 REST 端点 + SSE 行为正确

后续 maintainer 手动

  • scripts/release.sh 26.5.13v1 — 创建 GitHub Release + 上传二进制 + 刷新 CF latest(需 GITHUB_TOKEN
Open in Web Open in Cursor 

cursoragent and others added 14 commits May 12, 2026 15:05
- TeamView 联系人抽屉对 source=web 且 displayName=默认值时显示橙提示条
- 新增「升级为命名联系人」dialog: 真实姓名 + 6 预设标签 chip + 4 档案模板
- 复用现有 PATCH /api/agents/:id/network/contacts/:cid, 0 后端改动

Co-authored-by: Zyling-ai <Zyling-ai@users.noreply.github.com>
- pkg/network/avatar.go: SaveAvatar / AvatarPath / DeleteAvatar + 1 MiB cap
- pkg/network/contact.go: Contact.AvatarPath 字段 + Summary.HasAvatar
- codec 写读支持 avatarPath frontmatter
- pkg/channel/feishu_avatar.go: 通过 /contact/v3/users 取 avatar_240 / 640 / origin
- pkg/channel/telegram_avatar.go: getUserProfilePhotos + 复用 downloadFileByID
- 两个 channel 在 store.Resolve 后异步触发(goroutine,per-process dedupe)
- internal/api/network.go: GET/POST/DELETE .../contacts/:cid/avatar
- TeamView 列表 + drawer 渲染真实头像,img 加载失败 fallback 首字母圆
- drawer 加上传/移除头像按钮(1 MiB / jpg-png-webp-gif 校验)
- 9 个新单测覆盖 size cap / ext fallback / round-trip / delete idempotent

Co-authored-by: Zyling-ai <Zyling-ai@users.noreply.github.com>
GoalsView 右侧 AI 对话面板已在主线实现完整(含 AI fill_goal JSON 自动填表)。
本次小增强:把侧栏 filterStatus / filterAgentId / 当前可见前 8 个目标也注入 system context,AI 现在能感知用户视野,做出更贴的建议。

Co-authored-by: Zyling-ai <Zyling-ai@users.noreply.github.com>
- internal/api/network_aggregate.go: GET /api/network/{contacts,chats}
  - 跨所有 agent 并发拉取 + 按 ID groupBy 去重 + perAgent[] 分解
  - DisplayName/Title 取 msgCount 最高的 perAgent,Tags union 合并
  - 查询参数:source / q / tag / limit (default 200, max 1000)
- TeamView 联系人 + 群聊 sub-tab 顶部加「📋 本地 / 🌐 全局」toggle
  - 全局视图:同 ID 跨 agent 合并展示 + agent 头像簇可点跳本地
- 10 个新单测覆盖去重 / displayName 选优 / tag union / q 过滤 / sort

Co-authored-by: Zyling-ai <Zyling-ai@users.noreply.github.com>
- pkg/toolaudit/: JSONL 按 UTC 日切日志 + 200 KiB inline cap + blobs/ 溢出
  - Entry: AgentID/SessionID/ToolCallID/Name/Input/Result/DurationMs/Error
  - Append / GetByID (14 天回溯 + 自动 rehydrate blob) / ListBySession / ListAll(filter, limit, offset)
- runner.Config 加 ToolAudit *toolaudit.Log 字段, executeTools 持久化全量
- chat.go + public_chat.go 注入 ToolAudit
- 4 个新 REST 端点:
  - GET /api/agents/:id/tool-audit/:toolCallId
  - GET /api/agents/:id/sessions/:sid/tool-audit
  - GET /api/agents/:id/tool-audit/blobs/:name
  - GET /api/tool-audit (跨 agent 全局列表 + 4 个 filter + 分页)
- AiChat 工具卡 INPUT/OUTPUT label 旁加「🔍 详情」按钮 → 内嵌 drawer 显示 full + 复制
- 新增 ToolAuditView.vue 全局审计页:
  - filter (agent/session/tool/date range) + 分页 + 表格 + 点击行/详情按钮开 drawer
- 路由 /tool-audit + 侧栏「🔍 工具审计」菜单项
- 11 个新单测覆盖 inline / blob overflow / list / pagination / nil-safe

Co-authored-by: Zyling-ai <Zyling-ai@users.noreply.github.com>
后端:
- pkg/tools/approval.go: Broker (singleton)
  - Request(ctx, agent, session, name, input, timeout) 阻塞等 Decide
  - Decide / ListPending / Subscribe / 默认 5min timeout 自动拒绝
  - AuditHook 在 approve/deny/expired 都触发
- pkg/tools/policy.go: ToolPolicy 加 Ask []string 字段, MergePolicy 合并
- pkg/tools/registry.go: Execute 检测 askNames -> 走 broker
- internal/api/approvals.go: 4 个端点 + SSE stream
  - GET /api/approvals/pending
  - POST /api/approvals/:id/{approve,deny}
  - GET /api/approvals/stream (EventSource, ?token= 兜底 auth)
- internal/api/chat.go: 调用 ApplyPolicy + WithApprovalBroker (修复之前 chat 路径跳过 policy 的 bug)
- cmd/aipanel/main.go: 创建 approval audit log (写入 pkg/aiteam/audit) + Broker 注入

前端:
- composables/useApprovals.ts: 全局 EventSource + pending 状态 store + REST helpers
- App.vue 顶栏 🔔 铃铛 + badge 数字 + popover 列 pending + 允许/拒绝按钮
- AgentDetailView 工具权限 tab 加「需审批 (Ask)」输入区 + 3 个快捷预设
- ToolPolicy ts 类型加 ask?: string[]

审批日志:
- 每次决策(approve/deny/expired)写入 pkg/aiteam/audit
  Subsystem=approval, Type=approval_approved/denied/expired
  Detail.{approvalId,toolName,approved,reason,by}
  即使 aiteam flags 全 off 仍然写

12 个新单测 (broker / registry integration / audit hook 触发)

Co-authored-by: Zyling-ai <Zyling-ai@users.noreply.github.com>
合并 6 个子项发布:
- B-05 Web 访客升级为命名联系人
- E-01 头像 API 拉取 + 缓存
- GoalsChat 助手 context 增强
- B-03 跨 agent 联系人/群聊聚合视图
- F-03 工具调用全量审计 + ToolAuditView
- F-01 工具审批 policy=ask 端到端(审批日志写 pkg/aiteam/audit)

README 顶层 P1 规划中清单收紧到剩余 4 项;
版本 badge 升到 26.5.12v1;
ui/dist 已 sync 到 cmd/aipanel/ui_dist (go:embed 生效);
make go-only 通过, 全套 Go 测试 -race -count=1 绿;
42 个新单测全部 ok

Co-authored-by: Zyling-ai <Zyling-ai@users.noreply.github.com>
- zyhive-linux-amd64: 26.5.12v1 (CGO_ENABLED=0 static, 26.2 MB)
- zyhive-darwin-arm64: 26.5.12v1 (CGO_ENABLED=0 PIE, 25.8 MB)
- 包含 ui_dist embed (B-05/E-01/B-03/F-03/F-01 全部 UI 改动)
- 包含本程所有后端改动 (avatar / aggregate / toolaudit / approval / chat policy fix)

注: scripts/release.sh GitHub Release 上传 + CF latest 刷新需由 maintainer
在 PR merge 到 main 后手动跑 (需 GITHUB_TOKEN)

Co-authored-by: Zyling-ai <Zyling-ai@users.noreply.github.com>
…4b\u8bd5

3 \u4e2a httptest \u7ea7\u522b\u7684 E2E \u6d4b\u8bd5\u9a8c\u8bc1\u5168\u94fe\u8def:
- TestApprovalE2E_ApproveFlow: SSE \u8ba2\u9605 \u2192 broker.Request \u542f\u52a8 \u2192 SSE \u6536\u5230 approval_request \u2192 REST POST approve \u2192 broker \u8fd4\u56de\u5141\u8bb8 \u2192 SSE \u6536\u5230 approval_resolved \u2192 audit hook approval_approved \u2192 pending \u6e05\u7a7a
- TestApprovalE2E_DenyFlow: \u62d2\u7edd\u5168\u94fe\u8def + audit approval_denied
- TestApprovalE2E_DecideUnknownReturns404: 404 \u8def\u5f84

\u8fd0\u884c -race -count=1 \u5168\u7eff (1.08s)

Co-authored-by: Zyling-ai <Zyling-ai@users.noreply.github.com>
pkg/network/avatar_race_test.go (3 tests):
- TestSaveAvatarConcurrentSameContact: 16 goroutines write avatars on same
  contact with mixed extensions; verifies frontmatter not torn + cleanup
- TestSaveAvatarConcurrentDifferentContacts: 12 unique contacts in parallel
- TestSaveAvatarThenDeleteRace: interleaved save+delete 30x; mutex correctness

internal/api/network_aggregate_q_test.go (2 tests):
- TestAggregateContactsQ_MultiByteSubstring: Chinese / emoji / case-insensitive
  English / mixed-script substring matching, 8 cases
- TestAggregateContactsQ_DoesNotPanicOnGarbage: malformed UTF-8 input

pkg/toolaudit/duration_test.go (3 tests):
- TestAuditDurationReflectsRealTime: DurationMs round-trips through JSONL
- TestAuditConcurrentAppendsKeepDurationConsistent: 30 concurrent appends with
  unique durations preserved per entry
- TestAuditEntryMarshalsToValidJSON: newlines, tabs, emoji, escaped paths
  survive marshal/unmarshal

Plus E2E approval flow tests (already pushed in prior commit).

Final sweep: go test -race -count=1 ./... -> all 27 packages green
(includes all aiteam experimental packages)

Co-authored-by: Zyling-ai <Zyling-ai@users.noreply.github.com>
… scope + event check

pkg/channel/feishu_probe.go (370 lines):
- Probe(ctx, appId, appSecret) one call detects all of:
  * Valid credentials (auto-detect CN vs International cloud)
  * Bot identity (name + avatar URL + published status)
  * Granted OAuth scopes vs ZyHive RequiredScopes (5 scopes)
  * im.message.receive_v1 subscription + WebSocket long-conn enabled
  * List of joined chats (for F4 dashboard)
- Returns ProbeResult.Error in a fixed vocabulary the wizard understands:
  auth_failed / app_not_published / missing_scopes /
  event_not_subscribed / long_conn_disabled / network / unknown
- 8s timeout per HTTP request; never hangs the wizard

pkg/channel/feishu_probe_test.go (9 tests):
- TestProbe_HappyPath: full happy flow
- TestProbe_AuthFailed_BadSecret
- TestProbe_AppNotPublished
- TestProbe_MissingScopes (reports 4 missing of 5 required)
- TestProbe_EventNotSubscribed
- TestProbe_LongConnDisabled (webhook channel instead of websocket)
- TestProbe_MissingRequiredFields
- TestProbeErrorClass (4 cases)
- TestProbeResultMarshalShape (frontend contract guard)

Includes rewriteTransport mock helper for httptest -> Feishu API simulation.

Co-authored-by: Zyling-ai <Zyling-ai@users.noreply.github.com>
Components:
- ui/src/components/FeishuSetupWizard.vue (new, 380+ lines):
  * Step 1: copy-to-clipboard config checklist + open Feishu app create page
  * Step 2: paste creds + one-click probe (shows bot avatar/name/published status on success)
  * Step 3: auto-fix block — for each missing scope/event subscription,
    deep-link directly to https://open.feishu.cn/app/{appId}/{auth,event,version}
    + 'I'm done, recheck' button that re-runs probe
  * Step 4: 10s real WS test + completion + joined-chats preview

UI integration:
- AgentDetailView channel dialog 'Add' flow: shows 'Launch wizard' as the
  primary action; manual form behind 'high-level' toggle
- Edit flow: keeps the existing minimal form (just appId / new secret / allowlist)
- onFeishuWizardDone: auto-stuffs creds back into channelForm + saves immediately

API helpers:
- networkApi.feishuProbe / feishuTestConnect
- FeishuProbeResult ts type matches Go shape

End-to-end smoke verified (HTTP 200 happy / 400 missing fields / 401 unauth /
test-connect returns structured error + latency).

Build clean: vue-tsc + vite + go build all pass.

Co-authored-by: Zyling-ai <Zyling-ai@users.noreply.github.com>
After saving a Feishu channel, the channel card now shows an expandable
'🪶 飞书状态' panel:
  - Bot avatar + name + open_id (refreshed via SDK probe)
  - Published / not-published tag
  - List of joined chats (groups / p2p / topics) with id snippet
  - Issues block: missing scopes / event not subscribed / long-conn disabled

Backend:
- GET /api/agents/:id/channels/:chId/feishu-status (admin auth)
  Reads stored appId+secret from manager, runs Probe internally,
  returns same ProbeResult shape. Secret never leaves server.

Frontend:
- AgentDetailView channel card auto-fetches status on first expand,
  shows refresh button for re-checks
- Compact summary row when collapsed (bot name + chat count badges)

End-to-end: build clean, route registration verified (HTTP 404 for
unknown agent, route resolves correctly to the new handler).

Co-authored-by: Zyling-ai <Zyling-ai@users.noreply.github.com>
…ries

- CHANGELOG: full [26.5.13v1] entry documenting F1 backend probe (370+ lines + 9 tests),
  4-step setup wizard (380+ lines), per-channel status panel, and the deliberate
  scope cut (F2 SDK migration / F4 write ops -> separate PRs)
- README version badge -> 26.5.13v1, recent-versions table appended
- Cross-compiled both prebuilt binaries:
  zyhive-linux-amd64 (26.2 MB) + zyhive-darwin-arm64 (25.9 MB)
- ui_dist synced to cmd/aipanel/ui_dist for go:embed

Total branch: 14 commits (8 from 26.5.12v1 + 6 from 26.5.13v1)

Co-authored-by: Zyling-ai <Zyling-ai@users.noreply.github.com>
@cursor cursor Bot changed the title feat(26.5.12v1): 第 4 程产品价值收官 — 6 子项 (B-05 / E-01 / GoalsChat / B-03 / F-03 / F-01) feat(26.5.12v1 + 26.5.13v1): P1 产品价值收官 (6 子项) + 飞书 UX 全面升级 (F1) May 16, 2026
@cursor cursor Bot merged commit 58dac7e into main May 16, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants