feat(26.5.12v1 + 26.5.13v1): P1 产品价值收官 (6 子项) + 飞书 UX 全面升级 (F1)#31
Merged
cursor[bot] merged 14 commits intoMay 16, 2026
Merged
Conversation
- 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
两个 release 一并交付
[26.5.12v1] — 第 4 程:产品价值收官(6 子项)
把 README 顶层 "P1 规划中" 清单一口气全做掉。
ed29a954e122066269a5832b43cecae430dpolicy=ask端到端af29ec16df4a019ceb76651 个新单测
-race全绿,端到端 smoke 通过。[26.5.13v1] — 飞书集成 UX 全面升级 (F1)
把"给 agent 绑定飞书机器人"从 10 步摸黑配置变成 30 秒可视化向导。
pkg/channel/feishu_probe.go一站式 probe + 9 单测b3f56bdFeishuSetupWizard.vue4 步向导 + deep links + auto-fix430e1cfc1aca9b58dac7e关键功能:
POST /api/feishu/probe:一次调用并发完成验证凭据 + 拉 bot 身份 + 检测 5 个 OAuth scope + 检测im.message.receive_v1订阅 + 长连接状态 + 列已加群open.feishu.cn/app/{appId}/{auth,event,version}+ 复制权限名 + 重新检测 (4) 启动测试 + 加群预览larksuite/oapi-sdk-go v3.7.5(+3 MB)为后续 F2 铺路调研结论:
累计指标
-race -count=1绿go test ./...跨 27 个包全绿cd ui && npm run build通过后续 maintainer 手动
scripts/release.sh 26.5.13v1— 创建 GitHub Release + 上传二进制 + 刷新 CF latest(需GITHUB_TOKEN)