feat(skills): unify meeting related skills (#2387)

* feat(skills): unify meeting guidance

* fix(meeting): restore domain boundary guidance

* docs(meeting): remove agent rollout qualification guidance

* docs(meeting): front-load skill routing description

* docs(meeting): refine identity and command guidance

* docs(meeting): clarify identity and pagination guidance

* docs(meeting): fix minutes todo detail command

* fix(meeting): clarify artifact query routing

* fix(meeting): improve live meeting skill recall

* fix(qualitygate): generate valid minute token placeholders

* fix(meeting): address unified skill review findings

* docs(meeting): add minutes permission guidance

* docs(lark-meeting): 更新SKILL.md并新增会议问答引导脚本

1. 优化SKILL.md表格排版与快速行动章节内容,新增批量获取当日会议脚本的使用说明
2. 新增meeting_qa_bootstrap.py脚本,实现一站式采集当日进行中、已结束会议及未来日程,生成可直接执行的命令引导

* docs(calendar): clarify today's meeting lookup

* revert(meeting): remove meeting Q&A bootstrap guidance

* fix(skills): register lark-meeting suite keywords

---------

Co-authored-by: maozhixiang <maozhixiang@bytedance.com>
This commit is contained in:
zhaoleibd
2026-08-21 10:49:46 +08:00
committed by GitHub
parent da371dc242
commit e525beb8d6
56 changed files with 1403 additions and 1654 deletions
+2 -3
View File
@@ -45,7 +45,7 @@ The official [Lark/Feishu](https://www.larksuite.com/) CLI tool, maintained by t
| 📚 Wiki | Create and manage knowledge spaces, nodes, and documents |
| 👤 Contact | Search users by name/email/phone, get user profiles |
| 📧 Mail | Browse, search, read emails, send, reply, forward, manage drafts, watch new mail |
| 🎥 Meetings | Search meeting records, query meeting minutes artifacts and recordings |
| 🎥 Meetings | Search live and historical meetings, inspect participants and artifacts, analyze transcripts, manage Minutes, and assist in meetings |
| 🕐 Attendance | Query personal attendance check-in records |
| ✍️ Approval | Query approval tasks, approve/reject/transfer tasks, cancel and CC instances |
| 🎯 OKR | Query, create, update OKRs; manage objective & key results, alignments, indicators and progress. |
@@ -151,9 +151,8 @@ lark-cli auth status
| `lark-contact` | Search users by name/email/phone, get user profiles |
| `lark-wiki` | Knowledge spaces, nodes, documents |
| `lark-event` | Real-time event subscriptions (WebSocket), regex routing & agent-friendly format |
| `lark-vc` | Search meeting records, query meeting minutes (summary, todos, transcript) |
| `lark-meeting` | Search live or historical meetings, inspect participants and artifacts, analyze transcripts, manage Minutes, and assist in meetings |
| `lark-whiteboard` | Whiteboard/chart DSL rendering |
| `lark-minutes` | Minutes metadata & AI artifacts (summary, todos, chapters); upload audio/video to create minutes, download media |
| `lark-openapi-explorer` | Explore underlying APIs from official docs |
| `lark-skill-maker` | Custom skill creation framework |
| `lark-attendance` | Query personal attendance check-in records |
+2 -3
View File
@@ -45,7 +45,7 @@
| 📚 知识库 | 创建和管理知识空间、节点和文档 |
| 👤 通讯录 | 按姓名/邮箱/手机号搜索用户、获取用户信息 |
| 📧 邮箱 | 浏览、搜索、阅读邮件,发送、回复、转发邮件,管理草稿,监听新邮件 |
| 🎥 视频会议 | 搜索会议记录、查询会议纪要产物与会议录制 |
| 🎥 视频会议 | 查询进行中或历史会议、参会人和会议产物,分析逐字稿,管理妙记并提供会中协助 |
| 🕐 考勤打卡 | 查询个人考勤打卡记录 |
| ✍️ 审批 | 查询审批任务、同意/拒绝/转交审批任务、撤回与抄送审批实例 |
| 🎯 OKR | 查询、创建、更新 OKR,管理目标、关键结果、对齐、指标和进展记录 |
@@ -152,9 +152,8 @@ lark-cli auth status
| `lark-contact` | 按姓名/邮箱/手机号搜索用户,获取用户信息 |
| `lark-wiki` | 知识空间、节点、文档 |
| `lark-event` | 实时事件订阅(WebSocket),支持正则路由与 Agent 友好格式 |
| `lark-vc` | 搜索会议记录、查询会议纪要产物(总结、待办、逐字稿) |
| `lark-meeting` | 查询进行中或历史会议、参会人和会议产物,分析逐字稿,管理妙记并提供会中协助 |
| `lark-whiteboard` | 画板/图表 DSL 渲染 |
| `lark-minutes` | 妙记元数据与 AI 产物(总结、待办、章节),上传音视频生成妙记,下载音视频文件 |
| `lark-openapi-explorer` | 从官方文档探索底层 API |
| `lark-skill-maker` | 自定义 skill 创建框架 |
| `lark-attendance` | 查询个人考勤打卡记录 |
+51
View File
@@ -0,0 +1,51 @@
# minutes
> skill: lark-meeting
## +search
### Skills
- lark-meeting/references/lark-minutes-search.md
## minutes get
## +detail
### Skills
- lark-meeting/references/lark-minutes-detail.md
## +download
### Skills
- lark-meeting/references/lark-minutes-download.md
## +upload
### Skills
- lark-meeting/references/lark-minutes-upload.md
## +update
### Skills
- lark-meeting/references/lark-minutes-update.md
## +speaker-replace
### Skills
- lark-meeting/references/lark-minutes-speaker-replace.md
## +word-replace
## +summary
### Skills
- lark-meeting/references/lark-minutes-summary.md
## +todo
### Skills
- lark-meeting/references/lark-minutes-todo.md
## +apply-permission
### Skills
- lark-meeting/references/lark-minutes-apply-permission.md
+12
View File
@@ -0,0 +1,12 @@
# note
> skill: lark-meeting
## +detail
### Skills
- lark-meeting/references/lark-note-detail.md
## +transcript
### Skills
- lark-meeting/references/lark-note-transcript.md
+44
View File
@@ -0,0 +1,44 @@
# vc
> skill: lark-meeting
## +search
### Skills
- lark-meeting/references/lark-vc-search.md
## +detail
### Skills
- lark-meeting/references/lark-vc-detail.md
## meeting get
## +recording
### Skills
- lark-meeting/references/lark-vc-recording.md
## +meeting-list-active
### Skills
- lark-meeting/references/lark-vc-meeting-list-active.md
## +meeting-events
### Skills
- lark-meeting/references/lark-vc-meeting-events.md
## +meeting-message-send
### Skills
- lark-meeting/references/lark-vc-meeting-message-send.md
## +meeting-join
### Skills
- lark-meeting/references/lark-vc-agent-meeting-join.md
## +meeting-leave
### Skills
- lark-meeting/references/lark-vc-agent-meeting-leave.md
@@ -0,0 +1,26 @@
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package affordance
import (
"os"
"testing"
)
func TestMeetingDomainsDeclareUnifiedSkill(t *testing.T) {
previousSource := mdSource
t.Cleanup(func() { SetSource(previousSource) })
SetSource(os.DirFS("../../affordance"))
for _, domain := range []string{"vc", "minutes", "note"} {
t.Run(domain, func(t *testing.T) {
if got, ok := DomainSkill(domain); !ok || got != "lark-meeting" {
t.Fatalf("DomainSkill(%s) = (%q, %v), want (lark-meeting, true)", domain, got, ok)
}
if got, ok := DomainSkills(domain); !ok || len(got) != 1 || got[0] != "lark-meeting" {
t.Fatalf("DomainSkills(%s) = (%v, %v), want ([lark-meeting], true)", domain, got, ok)
}
})
}
}
+1 -1
View File
@@ -382,7 +382,7 @@ func fakeValueFromPlaceholderName(name string) (string, bool) {
case hasPlaceholderToken(tokens, "meeting"):
return "meeting_test123", true
case hasPlaceholderToken(tokens, "minute"):
return "obcn_test123", true
return "obcntest123", true
case hasPlaceholderToken(tokens, "task"):
return "task_test123", true
case hasPlaceholderToken(tokens, "item"):
+30
View File
@@ -165,6 +165,36 @@ func TestRunDryRunsMaterializesTypedPlaceholderFlagValues(t *testing.T) {
}
}
func TestRunDryRunsMaterializesValidMinuteTokenPlaceholder(t *testing.T) {
cliBin, argsPath := fakeDryRunCLI(t, `{"api":[{"method":"GET","url":"/open-apis/minutes/v1/minutes/obcntest123"}]}`)
m := manifest.Manifest{Commands: []manifest.Command{{
Path: "minutes +detail",
Runnable: true,
Flags: []manifest.Flag{
{Name: "minute-tokens", TakesValue: true},
{Name: "dry-run"},
},
}}}
ex := skillscan.Example{
Raw: "lark-cli minutes +detail --minute-tokens <minute_token>",
SourceFile: "skills/lark-meeting/scenes/create-and-edit-minutes.md",
Line: 28,
HasPlaceholder: true,
}
diags, facts := RunDryRuns(context.Background(), cliBin, m, []skillscan.Example{ex})
if len(diags) != 0 {
t.Fatalf("RunDryRuns() diagnostics = %#v", diags)
}
if len(facts) != 1 || !facts[0].Executable || facts[0].SkipReason != "" {
t.Fatalf("placeholder example should be executable after materialization: %#v", facts)
}
wantArgs := []string{"minutes", "+detail", "--minute-tokens", "obcntest123", "--dry-run"}
if gotArgs := readArgs(t, argsPath); !reflect.DeepEqual(gotArgs, wantArgs) {
t.Fatalf("fake CLI args = %#v, want %#v", gotArgs, wantArgs)
}
}
func TestRunDryRunsIgnoresTrailingShellComment(t *testing.T) {
cliBin, argsPath := fakeDryRunCLI(t, `{"api":[{"method":"GET","url":"/open-apis/docx/v1/documents/doccnxxxx"}]}`)
m := manifest.Manifest{Commands: []manifest.Command{{
+2
View File
@@ -20,7 +20,9 @@
{ "prefix": "shortcuts/event/", "labelDomains": [], "e2eDomains": ["event"] },
{ "prefix": "skills/lark-im/", "labelDomains": ["im"], "e2eDomains": ["im"] },
{ "prefix": "skills/lark-meeting/", "labelDomains": ["vc"], "e2eDomains": ["vc", "minutes", "note"] },
{ "prefix": "skills/lark-vc/", "labelDomains": ["vc"], "e2eDomains": ["vc"] },
{ "prefix": "skills/lark-vc-agent/", "labelDomains": ["vc"], "e2eDomains": ["vc"] },
{ "prefix": "skills/lark-doc/", "labelDomains": ["ccm"], "e2eDomains": ["docs"] },
{ "prefix": "skills/lark-wiki/", "labelDomains": ["ccm"], "e2eDomains": ["wiki"] },
{ "prefix": "skills/lark-drive/", "labelDomains": ["ccm"], "e2eDomains": ["drive"] },
+9
View File
@@ -87,6 +87,15 @@ test("uses shared map for skill domain changes", () => {
assert.match(output.live_packages, /github\.com\/larksuite\/cli\/tests\/cli_e2e\/sheets/);
});
test("runs every meeting package for the consolidated meeting skill", () => {
const output = runDomains(["skills/lark-meeting/scenes/query-meeting-and-artifacts.md"]);
assert.equal(output.mode, "subset");
assert.equal(output.domains, "minutes,note,vc");
assert.match(output.live_packages, /github\.com\/larksuite\/cli\/tests\/cli_e2e\/minutes/);
assert.match(output.live_packages, /github\.com\/larksuite\/cli\/tests\/cli_e2e\/note/);
assert.match(output.live_packages, /github\.com\/larksuite\/cli\/tests\/cli_e2e\/vc/);
});
test("falls back to full when a mapped path has no e2e package", () => {
const output = runDomains(["shortcuts/whiteboard/export.go"]);
assert.equal(output.mode, "full");
+31 -16
View File
@@ -37,31 +37,34 @@ func readSkillDoc(t *testing.T, relPath string) string {
}
// TestMinutesBotShortcutsIdentityDocsMatchAuthTypes pins that every minutes
// shortcut declared bot-capable in code is documented as such in the main
// SKILL.md identity line, so the two sources can't silently diverge again.
// shortcut declared bot-capable in code is documented as such in the
// lark-meeting reference that owns the command guidance.
func TestMinutesBotShortcutsIdentityDocsMatchAuthTypes(t *testing.T) {
skill := readSkillDoc(t, "skills/lark-minutes/SKILL.md")
skill := readSkillDoc(t, "skills/lark-meeting/SKILL.md")
for _, cmd := range []struct {
name string
authTypes []string
reference string
}{
{"+search", MinutesSearch.AuthTypes},
{"+detail", MinutesDetail.AuthTypes},
{"+download", MinutesDownload.AuthTypes},
{"+apply-permission", MinutesApplyPermission.AuthTypes},
{"+search", MinutesSearch.AuthTypes, "lark-minutes-search.md"},
{"+detail", MinutesDetail.AuthTypes, "lark-minutes-detail.md"},
{"+download", MinutesDownload.AuthTypes, "lark-minutes-download.md"},
{"+apply-permission", MinutesApplyPermission.AuthTypes, "lark-minutes-apply-permission.md"},
} {
if !hasAuthType(cmd.authTypes, "bot") {
t.Errorf("%s AuthTypes = %v, want bot included", cmd.name, cmd.authTypes)
continue
}
token := "`" + cmd.name + "`"
if !strings.Contains(skill, token) {
t.Errorf("skills/lark-minutes/SKILL.md identity section must mention %s alongside its bot support", token)
if !strings.Contains(skill, "references/"+cmd.reference) {
t.Errorf("skills/lark-meeting/SKILL.md must link %s to %s", cmd.name, cmd.reference)
}
reference := readSkillDoc(t, "skills/lark-meeting/references/"+cmd.reference)
for _, identity := range []string{"--as user", "--as bot"} {
if !strings.Contains(reference, identity) {
t.Errorf("%s must document %s support for %s", cmd.reference, identity, cmd.name)
}
}
}
if !strings.Contains(skill, "也支持 `--as bot`") {
t.Error("skills/lark-minutes/SKILL.md identity section must state which commands also support --as bot")
}
}
@@ -74,16 +77,28 @@ func TestMinutesApplyPermissionHasReference(t *testing.T) {
t.Fatalf("MinutesApplyPermission.AuthTypes = %v, want bot included (this PR's contract)", MinutesApplyPermission.AuthTypes)
}
reference := readSkillDoc(t, "skills/lark-minutes/references/lark-minutes-apply-permission.md")
reference := readSkillDoc(t, "skills/lark-meeting/references/lark-minutes-apply-permission.md")
for _, must := range []string{"--as bot", "--as user", "身份", "missing scope"} {
if !strings.Contains(reference, must) {
t.Errorf("lark-minutes-apply-permission.md must cover %q (user/bot identity + scope-vs-ACL guidance)", must)
}
}
skill := readSkillDoc(t, "skills/lark-meeting/SKILL.md")
if !strings.Contains(skill, "references/lark-minutes-apply-permission.md") {
t.Error("skills/lark-meeting/SKILL.md command table must link +apply-permission to its reference doc")
}
}
func TestLegacyMinutesSkillRoutesToMeetingSkill(t *testing.T) {
skill := readSkillDoc(t, "skills/lark-minutes/SKILL.md")
if !strings.Contains(skill, "[`+apply-permission`](references/lark-minutes-apply-permission.md)") {
t.Error("skills/lark-minutes/SKILL.md Shortcuts table must link +apply-permission to its reference doc")
for _, must := range []string{
"本技能只用于兼容旧名称,不直接处理业务。",
"../lark-meeting/SKILL.md",
} {
if !strings.Contains(skill, must) {
t.Errorf("skills/lark-minutes/SKILL.md must preserve compatibility routing %q", must)
}
}
}
+40 -8
View File
@@ -42,12 +42,12 @@ func TestNoteIdentityDocsMatchAuthTypes(t *testing.T) {
t.Fatalf("NoteTranscript.AuthTypes = %v now includes bot; update the bot+unified stop-path guidance below (and this test) instead of leaving it stale", NoteTranscript.AuthTypes)
}
skill := readSkillDoc(t, "skills/lark-note/SKILL.md")
if !strings.Contains(skill, "`+detail` 支持 `--as user` / `--as bot`") {
t.Error("skills/lark-note/SKILL.md must state that +detail supports both user and bot")
scene := readSkillDoc(t, "skills/lark-meeting/scenes/query-note-and-artifacts.md")
if !strings.Contains(scene, "`note +detail` 支持 `--as user` / `--as bot`") {
t.Error("query-note-and-artifacts.md must state that note +detail supports both user and bot")
}
if !strings.Contains(skill, "`+transcript` 仅支持 `--as user`") {
t.Error("skills/lark-note/SKILL.md must state that +transcript is user-only (matches NoteTranscript.AuthTypes)")
if !strings.Contains(scene, "`note +transcript` 仅支持 `--as user`") {
t.Error("query-note-and-artifacts.md must state that note +transcript is user-only (matches NoteTranscript.AuthTypes)")
}
}
@@ -57,9 +57,9 @@ func TestNoteIdentityDocsMatchAuthTypes(t *testing.T) {
// letting an agent silently drop --as and switch identity.
func TestNoteUnifiedBotStopPathIsDocumented(t *testing.T) {
for _, path := range []string{
"skills/lark-note/SKILL.md",
"skills/lark-note/references/lark-note-detail.md",
"skills/lark-note/references/lark-note-transcript.md",
"skills/lark-meeting/scenes/query-note-and-artifacts.md",
"skills/lark-meeting/references/lark-note-detail.md",
"skills/lark-meeting/references/lark-note-transcript.md",
} {
content := readSkillDoc(t, path)
if !strings.Contains(content, "bot") || !strings.Contains(content, "user") {
@@ -67,3 +67,35 @@ func TestNoteUnifiedBotStopPathIsDocumented(t *testing.T) {
}
}
}
func TestLegacyNoteSkillRoutesToMeetingSkill(t *testing.T) {
skill := readSkillDoc(t, "skills/lark-note/SKILL.md")
for _, must := range []string{
"本技能只用于兼容旧名称,不直接处理业务。",
"../lark-meeting/SKILL.md",
} {
if !strings.Contains(skill, must) {
t.Errorf("skills/lark-note/SKILL.md must preserve compatibility routing %q", must)
}
}
}
func TestMeetingNoteCoverHandlingIsReachable(t *testing.T) {
noteScene := readSkillDoc(t, "skills/lark-meeting/scenes/query-note-and-artifacts.md")
for _, must := range []string{
"第一个 `<whiteboard",
"docs +media-download",
"--type whiteboard",
"./notes/<note_id>/cover",
"--as <source_identity>",
} {
if !strings.Contains(noteScene, must) {
t.Errorf("query-note-and-artifacts.md must preserve note cover handling %q", must)
}
}
meetingScene := readSkillDoc(t, "skills/lark-meeting/scenes/query-meeting-and-artifacts.md")
if !strings.Contains(meetingScene, "query-note-and-artifacts.md") {
t.Error("query-meeting-and-artifacts.md must route intelligent-note body handling to the owning Note scene")
}
}
+40 -16
View File
@@ -35,18 +35,18 @@ func readSkillDoc(t *testing.T, relPath string) string {
}
// TestVCSearchIdentityDocsMatchAuthTypes pins that `+search` stays user-only
// in both code and docs. If AuthTypes ever gains "bot", this test forces a
// deliberate update to the SKILL.md/reference wording below instead of
// in both code and the reference owned by lark-meeting. If AuthTypes ever
// gains "bot", this test forces a deliberate documentation update instead of
// letting the docs silently fall out of sync.
func TestVCSearchIdentityDocsMatchAuthTypes(t *testing.T) {
skill := readSkillDoc(t, "skills/lark-vc/SKILL.md")
reference := readSkillDoc(t, "skills/lark-vc/references/lark-vc-search.md")
skill := readSkillDoc(t, "skills/lark-meeting/SKILL.md")
reference := readSkillDoc(t, "skills/lark-meeting/references/lark-vc-search.md")
if hasAuthType(VCSearch.AuthTypes, "bot") {
t.Fatalf("VCSearch.AuthTypes = %v now includes bot; update skills/lark-vc/SKILL.md and lark-vc-search.md wording (and this test) to reflect the new support instead of leaving the user-only claims below", VCSearch.AuthTypes)
t.Fatalf("VCSearch.AuthTypes = %v now includes bot; update skills/lark-meeting/references/lark-vc-search.md wording (and this test) to reflect the new support instead of leaving the user-only claim below", VCSearch.AuthTypes)
}
if !strings.Contains(skill, "`+search` 仅支持 `--as user`") {
t.Error("skills/lark-vc/SKILL.md must state that `+search` only supports --as user (matches VCSearch.AuthTypes)")
if !strings.Contains(skill, "references/lark-vc-search.md") {
t.Error("skills/lark-meeting/SKILL.md must link to the vc +search reference")
}
if !strings.Contains(reference, "仅支持 `user` 身份") && !strings.Contains(reference, "仅 `--as user`") {
t.Error("lark-vc-search.md must state that +search only supports user identity (matches VCSearch.AuthTypes)")
@@ -55,27 +55,51 @@ func TestVCSearchIdentityDocsMatchAuthTypes(t *testing.T) {
// TestVCBotShortcutsIdentityDocsMatchAuthTypes pins that the VC shortcuts this
// PR opened to bot (`+detail`, `+recording`) are both declared bot-capable in
// code and documented as such in the main SKILL.md identity line.
// code and documented as such in their lark-meeting references.
func TestVCBotShortcutsIdentityDocsMatchAuthTypes(t *testing.T) {
skill := readSkillDoc(t, "skills/lark-vc/SKILL.md")
skill := readSkillDoc(t, "skills/lark-meeting/SKILL.md")
for _, cmd := range []struct {
name string
authTypes []string
reference string
}{
{"+detail", VCDetail.AuthTypes},
{"+recording", VCRecording.AuthTypes},
{"+detail", VCDetail.AuthTypes, "lark-vc-detail.md"},
{"+recording", VCRecording.AuthTypes, "lark-vc-recording.md"},
} {
if !hasAuthType(cmd.authTypes, "bot") {
t.Errorf("%s AuthTypes = %v, want bot included (this PR's contract)", cmd.name, cmd.authTypes)
continue
}
token := "`" + cmd.name + "`"
if !strings.Contains(skill, token) {
t.Errorf("skills/lark-vc/SKILL.md identity section must mention %s alongside its bot support", token)
if !strings.Contains(skill, "references/"+cmd.reference) {
t.Errorf("skills/lark-meeting/SKILL.md must link %s to %s", cmd.name, cmd.reference)
}
reference := readSkillDoc(t, "skills/lark-meeting/references/"+cmd.reference)
for _, identity := range []string{"--as user", "--as bot"} {
if !strings.Contains(reference, identity) {
t.Errorf("%s must document %s support for %s", cmd.reference, identity, cmd.name)
}
}
}
if !strings.Contains(skill, "也支持 `--as bot`") {
t.Error("skills/lark-vc/SKILL.md identity section must state which commands also support --as bot")
}
func TestMeetingArtifactSceneDelegatesToDomainOwners(t *testing.T) {
scene := readSkillDoc(t, "skills/lark-meeting/scenes/query-meeting-and-artifacts.md")
for _, target := range []string{
"query-note-and-artifacts.md",
"query-minutes-and-artifacts.md",
} {
if !strings.Contains(scene, target) {
t.Errorf("query-meeting-and-artifacts.md must delegate to %s", target)
}
}
for _, duplicatedCommand := range []string{
"lark-cli note +detail",
"lark-cli minutes +detail",
} {
if strings.Contains(scene, duplicatedCommand) {
t.Errorf("query-meeting-and-artifacts.md must not duplicate downstream command %q", duplicatedCommand)
}
}
}
+5 -4
View File
@@ -11,8 +11,9 @@
"lark-im": ["即时通讯", "消息", "群聊"],
"lark-mail": ["邮箱", "邮件"],
"lark-markdown": ["Markdown 文档", ".md", "MD 文件"],
"lark-minutes": ["妙记", "音视频转写", "/minutes/"],
"lark-note": ["会议纪要"],
"lark-meeting": ["视频会议", "会议记录", "会议产物", "智能纪要", "妙记", "会议录制", "会议内容", "智能体入会", "/minutes/"],
"lark-minutes": ["lark-minutes"],
"lark-note": ["lark-note"],
"lark-okr": ["OKR"],
"lark-openapi-explorer": ["开放平台文档", "OpenAPI"],
"lark-shared": ["授权", "配置", "登录", "登录态", "身份", "版本", "更新"],
@@ -20,8 +21,8 @@
"lark-skill-maker": ["CLI Skill", "自定义 Skill", "能力封装"],
"lark-slides": ["演示文稿", "幻灯片", "PPT", "/slides/"],
"lark-task": ["任务", "待办", "任务智能体", "父任务", "子任务", "负责人", "截止时间", "任务清单", "任务搜索", "多步任务", "任务提醒"],
"lark-vc": ["视频会议", "会议纪要"],
"lark-vc-agent": ["会中能力", "视频会议机器人"],
"lark-vc": ["lark-vc"],
"lark-vc-agent": ["lark-vc-agent"],
"lark-whiteboard": ["画板", "图表"],
"lark-wiki": ["知识库", "知识空间", "空间目录", "/wiki/"],
"lark-workflow-meeting-summary": ["会议纪要工作流", "会议纪要", "会议周报"],
+7 -6
View File
@@ -1,7 +1,7 @@
---
name: lark-calendar
version: 1.0.0
description: "飞书日历:管理日历日程和会议室。查看/搜索日程、创建/更新日程、管理参会人、查询忙闲和推荐时段、预定会议室。当用户需要查看日程安排、创建/修改会议、查询/预定会议室时使用。不负责:查询过去的视频会议记录(走 lark-vc)、待办任务(走 lark-task)。"
description: "飞书日历:管理日历日程和会议室。查看/搜索日程、创建/更新日程、管理参会人、查询忙闲和推荐时段、预定会议室。当用户需要查看日程安排、创建/修改会议、查询/预定会议室时使用。不负责:查询过去的视频会议记录(走 lark-meeting)、待办任务(走 lark-task)。"
metadata:
requires:
bins: ["lark-cli"]
@@ -127,11 +127,12 @@ lark-cli calendar +freebusy --start 2026-03-11 --end 2026-03-12 --user-id ou_xxx
| 用户意图 | 路由到 |
|----------|--------|
| 查询过去的会议("昨天的会议""上周的会" | [`../lark-vc/SKILL.md`](../lark-vc/SKILL.md)(会议数据含即时会议,仅查日程会遗漏) |
| 查询过去的会议("昨天的会议""上周的会" | [`../lark-meeting/SKILL.md`](../lark-meeting/SKILL.md)(会议数据含即时会议,仅查日程会遗漏) |
| 今天有哪些会议| 需要合并两部分内容:[`../lark-meeting/SKILL.md`](../lark-meeting/SKILL.md) 中的 `vc +search` 查询今天已结束的会议, `calendar +agenda` 查询进行中或未开始的日程。|
| 查询日历/日程或未来时间的会议 | 本 skill |
| 按关键词搜索日程 | 本 skill(`+search-event` |
| 从日程获取关联的视频会议 ID 或用户绑定的会议纪要文档 | 本 skill(`+meeting` |
| 从日程进一步拿 AI 智能纪要 / 逐字稿 / 妙记产物 | 先 `+meeting``meeting_id`,再 [`vc +detail`](../lark-vc/references/lark-vc-detail.md) → [`note +detail`](../lark-note/references/lark-note-detail.md) / [`minutes +detail`](../lark-minutes/references/lark-minutes-detail.md) |
| 从日程进一步拿 AI 智能纪要 / 逐字稿 / 妙记产物 | 先 `+meeting``meeting_id`,再进入 [`lark-meeting`](../lark-meeting/SKILL.md)[`vc +detail`](../lark-meeting/references/lark-vc-detail.md) → [`note +detail`](../lark-meeting/references/lark-note-detail.md) / [`minutes +detail`](../lark-meeting/references/lark-minutes-detail.md) |
| 预约/改约日程、调整时间、添加/更换会议室、查会议室 | 先判断新建 vs 编辑,再进入 [schedule-meeting 工作流](references/lark-calendar-schedule-meeting.md) |
| 仅编辑日程字段(标题/描述)或增删参会人(不涉及时间和会议室) | 先定位 `event_id`,再读 [+update](references/lark-calendar-update.md) 执行变更 |
| 编辑/删除重复性日程(「改这个重复日程」「删掉后面的」「全部取消」等) | 先读 [重复性日程操作规范](references/lark-calendar-recurring.md),确认操作范围后执行 |
@@ -165,8 +166,8 @@ lark-cli calendar <resource> <method> [flags]
# 查询用户主日历
lark-cli calendar calendars primary
# 获取日程分享链接
lark-cli calendar events share_info --calendar-id <calendar_id> --event-id <event_id>
# 获取日程详情及 app_link
lark-cli calendar events get --calendar-id <calendar_id> --event-id <event_id>
# 删除日程
lark-cli calendar events delete --calendar-id <calendar_id> --event-id <event_id>
@@ -196,7 +197,7 @@ lark-cli im +chat-search --query <query> --as user
## 不在本 skill 范围
- 查询过去的视频会议记录 → [lark-vc](../lark-vc/SKILL.md)
- 查询过去的视频会议记录 → [lark-meeting](../lark-meeting/SKILL.md)
- 待办任务管理 → [lark-task](../lark-task/SKILL.md)
- 通讯录 → [lark-contact](../lark-contact/SKILL.md)
- 即时通讯 → [lark-im](../lark-im/SKILL.md)
+1 -1
View File
@@ -127,7 +127,7 @@ lark-cli docs +fetch --doc Z1Fj...tnAc --scope section --start-block-id blkTitle
|`<whiteboard>`|提取 `token`,使用 `docs +media-download`|
|`<sheet>``<cite file-type="sheets">`|提取 `token``sheet-id`,转到 [`lark-sheets`](../../lark-sheets/SKILL.md)|
|`<bitable>``<cite file-type="bitable">`|提取 `token``table-id`,转到 [`lark-base`](../../lark-base/SKILL.md)|
|`<vc-transcribe-tab>`|提取 `vc-node-id`,使用 [`lark-note`](../../lark-note/SKILL.md) 的 `note +detail`|
|`<vc-transcribe-tab>`|提取 `vc-node-id`,使用 [`lark-meeting`](../../lark-meeting/SKILL.md) 的 `note +detail`|
|`<synced_reference>`|提取 `src-token``src-block-id`,读取源文档并定位 block|
## 参考
+146
View File
@@ -0,0 +1,146 @@
---
name: lark-meeting
version: 1.0.0
description: "飞书视频会议:查询会议记录与会议产物(纪要/逐字稿/妙记)、妙记搜索/上传/下载/编辑、机器人参与会议;查询进行中的会议、实时会议内容(发言/聊天/共享文档)问答(会上/会里)、发送会中聊天/表情;基于 meeting_id、meeting_no、event_id、note_id、minute_token、vc-node-id 或妙记 URL 查询相关信息。预约会议、忙闲和会议室管理走 lark-calendar。"
metadata:
requires:
bins: ["lark-cli"]
cliHelp: "lark-cli vc --help;lark-cli minutes --help;lark-cli note --help"
---
# lark-meeting
飞书视频会议业务的统一入口,支持查询会议记录、实时会议互动、管理妙记、阅读智能纪要等操作。本技能负责领域关系、任务路由和跨命令编排。
无需预读 [`lark-shared`](../lark-shared/SKILL.md) 或预跑 `auth status --verify`,仅遇到未认证、token / 身份或 scope 错误时读取该 Skill,修复后重试。认证、身份或 scope 管理请求则直接使用该 Skill。
## 身份初始化与延续
`source_identity` 作为跨命令工作流的状态:
1. 上下文已有来源身份:严格沿用。用户要求切换时先说明身份连续性和权限影响,不静默切换。
2. 没有来源身份,用户明确指定身份:使用用户指定的 `--as`
3. 没有来源身份且用户未指定:操作语义明确要求应用机器人时使用 `--as bot`,否则显式使用 `--as user`
确定 `source_identity` 后,再检查目标命令是否支持该身份:
- 支持:显式传入并继续执行。
- 不支持:说明限制并停止;不要为了让命令成功而替换身份。
- 只有用户明确同意切换身份后,才以新身份重新开始一条工作流。
## 领域模型与概念
```text
[会议来源]
Calendar 日程 (event_id) ──预约或关联──┐
即时会议(无 event_id)────────────────┴──► 会议 (meeting_id)
Calendar 日程 ──meeting_note────────────► Doc(用户纪要,独立于 AI 智能纪要)
[会议产物]
会议 (meeting_id)
├── AI 总结 ──► Note 智能纪要 (note_id)
│ ├── 智能纪要文档 ───────────► Doc (note_doc_token)
│ ├── 逐字稿
│ │ ├── normal ──────────► Doc (verbatim_doc_token)
│ │ └── unified ──────────► note +transcript(非独立 Doc
│ └── 共享文档 ──────────────► Doc (shared_doc_tokens)
└── 录制 ──► Minutes 妙记 (minute_token)
├── AI 产物:Summary / Todo / Chapter / Keyword
├── Transcript(文字记录)
└── 原始音视频
本地音视频 ─────────────────────────────► Minutes 妙记 (minute_token)
```
| 对象 | 主标识 | 概念与关系 |
|---|---|---|
| Calendar 日程 | `event_id` | 日历上的日程,包含时间、参与人、会议室和 RSVP,可预约或关联 VC 会议;不是完整的会议记录。日程上的 `meeting_note` 是用户手工绑定的 Doc,与 AI 智能纪要无关。 |
| Meeting 会议 | `meeting_id` | 实际发生的视频会议,可以来自 Calendar,也可以是没有日程的即时会议。会议主题、时间、参会人快照和会中事件属于会议数据;Note 与 Minutes 是它可能关联的会后产物。 |
| Note 智能纪要 | `note_id` | 开启 AI 总结后形成的逻辑产物集合。`note_display_type` 决定获取逐字稿中文字记录的不同方式。 |
| Minutes 妙记 | `minute_token` | 由会议录制或本地音视频上传生成,包含总结、待办、章节、关键词、文字记录和原始音视频;可以关联 VC 会议,也可以独立存在。 |
| Doc 文档 | Doc token | 内容载体,不是会议标识。`note_doc_token``shared_doc_tokens` 和部分 `verbatim_doc_token` 指向 DocDoc token 不能当作 `note_id``meeting_id`。 |
### 核心标识
- `meeting_id`:会议 ID。长数字字符串,不是 9 位会议号。
- `meeting_no`:会议号。9 位纯数字;CLI 参数名为 `--meeting-number`
- `minute_token`:妙记 Token。小写字母数字串,通常取自妙记 URL `/minutes/<minute_token>`
以上标识均按字符串原样传递,不能相互替代。
### 领域不变量
- Note 与 Minutes 分别来自 AI 总结和录制两条独立链路。一场会议可能同时有两类产物、只有其中一类,也可能都没有;不能根据 `note_id` 推断必然存在 `minute_token`,反之亦然。
- Minutes 可以由本地音视频直接生成,因此不一定关联 `meeting_id` 或 Calendar `event_id`
- Calendar `meeting_note`、Note `note_id`、Minutes `minute_token` 和各类 Doc token 标识不同对象,不能互换、代入其他域的命令或从一者反推另一者。
## 快速行动
### 查询进行中的会议内容
```bash
# 当前用户所在会议
lark-cli vc +meeting-list-active --as user
# 应用机器人可见的目标用户会议
lark-cli vc +meeting-list-active --as bot --user-id <open_id>
# 确定唯一 meeting_id 后沿用来源身份
lark-cli vc +meeting-events --as <source_identity> --meeting-id <meeting_id> --page-all --format pretty
```
同时有多场会议时,需要先选择要查询的会议;只有一场会议时,直接查询该场会议的会议事件。
应用身份只返回“目标用户正在参会、且应用机器人也在同一会议中”的会议;返回空不代表目标用户没有在开会。向用户说明结果时使用“用户身份”或“应用身份”,不要暴露 `user` / `bot` 这类内部缩写。
## 场景手册
当任务目标与场景匹配时,阅读对应的场景手册,按流程执行任务。
- [查询会议及其产物](scenes/query-meeting-and-artifacts.md):按主题、时间、参会人或 `meeting_id` / `meeting_no` / `event_id` 定位历史会议;查询参会人、录像和会议关联的智能纪要或妙记;基于会议记录总结或复盘。
- [查询妙记及其产物](scenes/query-minutes-and-artifacts.md):已有妙记 URL / `minute_token`,或按标题、所有者、参与者搜索妙记;读取总结、待办、章节、关键词、逐字稿,下载原始音视频,或查询关联智能纪要。
- [生成和修改妙记、管理妙记权限](scenes/create-and-edit-minutes.md):将本地音视频生成妙记、逐字稿、总结、待办或章节;修改妙记标题、总结、待办、关键词或说话人;申请妙记权限,或查看、分配妙记协作者权限。
- [查询智能纪要及关联产物](scenes/query-note-and-artifacts.md):已有 `note_id`、智能纪要 Docx URL/token,或需要查询纪要正文、逐字稿、妙记和共享文档等关联产物。
- [应用机器人参会与会中互动](scenes/live-meeting-attend.md):完整编排应用机器人的活跃会议发现、真实入会、事件拉取、文本/表情互动和明确授权后的离会。
- [会中事件与会中互动](scenes/live-meeting-interact.md):在不触发新的入会/离会操作时,使用用户身份或已在会中的应用身份查询活跃会议、查看发言/聊天/共享内容,或发送文本和表情。
## 命令参考
| 命令 | 用途 | 参考方式 |
|---|---|---|
| `vc +search` | 搜索历史会议 | [lark-vc-search](references/lark-vc-search.md) |
| `vc +detail` | 查询会议信息及关联的 Note、Minutes 标识 | [lark-vc-detail](references/lark-vc-detail.md) |
| `vc meeting get` | 查询会议基础信息和参会人快照 | `lark-cli vc meeting get --help` |
| `vc +recording` | 从会议定位录制及妙记 | [lark-vc-recording](references/lark-vc-recording.md) |
| `vc +meeting-list-active` | 发现当前可见的进行中会议 | [lark-vc-meeting-list-active](references/lark-vc-meeting-list-active.md) |
| `vc +meeting-events` | 读取会中事件和共享内容 | [lark-vc-meeting-events](references/lark-vc-meeting-events.md) |
| `vc +meeting-message-send` | 发送会中文本消息或表情 | [lark-vc-meeting-message-send](references/lark-vc-meeting-message-send.md) |
| `vc +meeting-join` | 让应用机器人加入会议 | [lark-vc-agent-meeting-join](references/lark-vc-agent-meeting-join.md) |
| `vc +meeting-leave` | 让应用机器人离开会议 | [lark-vc-agent-meeting-leave](references/lark-vc-agent-meeting-leave.md) |
| `minutes +search` | 搜索妙记 | [lark-minutes-search](references/lark-minutes-search.md) |
| `minutes minutes get` | 查询妙记基础信息 | `lark-cli minutes minutes get --help` |
| `minutes +detail` | 读取妙记信息和指定产物 | [lark-minutes-detail](references/lark-minutes-detail.md) |
| `minutes +download` | 下载妙记原始音视频 | [lark-minutes-download](references/lark-minutes-download.md) |
| `minutes +upload` | 从云空间音视频生成妙记 | [lark-minutes-upload](references/lark-minutes-upload.md) |
| `minutes +update` | 修改妙记标题 | [lark-minutes-update](references/lark-minutes-update.md) |
| `minutes +speaker-replace` | 替换妙记逐字稿说话人 | [lark-minutes-speaker-replace](references/lark-minutes-speaker-replace.md) |
| `minutes +summary` | 替换妙记 AI 总结 | [lark-minutes-summary](references/lark-minutes-summary.md) |
| `minutes +todo` | 增删改妙记 AI 待办 | [lark-minutes-todo](references/lark-minutes-todo.md) |
| `minutes +apply-permission` | 申请妙记查看或编辑权限 | [lark-minutes-apply-permission](references/lark-minutes-apply-permission.md) |
| `drive +member-list` | 查看妙记协作者及其权限 | [lark-drive-member-list](../lark-drive/references/lark-drive-member-list.md) |
| `drive +member-add` | 给指定成员分配妙记查看或编辑权限 | [lark-drive-member-add](../lark-drive/references/lark-drive-member-add.md) |
| `minutes +word-replace` | 批量替换妙记逐字稿关键词 | `lark-cli minutes +word-replace --help` |
| `note +detail` | 查询智能纪要及关联文档标识 | [lark-note-detail](references/lark-note-detail.md) |
| `note +transcript` | 获取 unified 智能纪要逐字稿 | [lark-note-transcript](references/lark-note-transcript.md) |
## 渐进加载规则
按“快速行动 → 场景手册 → 命令参考”渐进加载:
1. 用户目标符合“快速行动”的进入条件时,直接执行对应 CLI;不要预读场景手册、命令参考、`--help` 或 schema。
2. 不符合快速行动条件,或缺少关键标识、需要消歧、涉及写操作时,读取与目标匹配的一个主场景手册;主场景明确转交到下游场景时,只继续读取被引用的场景或章节,并按其中流程执行 CLI。
3. 仅当缺少具体参数、返回字段、特殊约束或异常处理方式时:有参考手册的命令读取对应文件;没有参考手册的命令运行表中列出的精确 `lark-cli ... --help`。场景或 reference 已给出精确命令时,不再调用 `--help`;仅在参数缺失、命令不识别或文档与运行结果冲突时调用。
@@ -88,8 +88,5 @@ lark-cli minutes +apply-permission --minute-token obcnxxxxxxxxxxxxxxxxxxxx --per
| `missing required scope(s)` | 当前身份缺少 `minutes:permission:apply` | 见上方「missing scope 与资源 ACL」 |
| 申请后仍无权限 | 所有者尚未同意 | 这是异步申请,需等待所有者处理;不代表命令执行失败 |
## 参考
- [lark-minutes](../SKILL.md) — 妙记全部命令
- [minutes +detail](lark-minutes-detail.md) — 妙记内容与产物查询
- [lark-shared](../../lark-shared/SKILL.md) — 身份延续与权限管理
## 相关场景
- [生成和修改妙记](../scenes/create-and-edit-minutes.md)
@@ -0,0 +1,52 @@
# minutes +detail
通过 `minute_token` 查询妙记详情,按需获取 AI 产物(总结/待办/章节/逐字稿/关键词)。只读,支持 `--as user` / `--as bot`
`minute_token` 由某个身份取得时,本命令及后续 `note +detail``docs +fetch` 都必须显式沿用同一个 `--as`
> `--summary` / `--todo` / `--chapter` / `--keyword` / `--transcript` 都是可选项;请求相应产物时必须显式传入,不传任何产物 flag 时只返回基础信息(如 `title`),AI 产物字段都不会出现。一次性获取所有产物:`--summary --todo --chapter --keyword --transcript`。
## 命令
```bash
# 仅基础信息
lark-cli minutes +detail --as <source_identity> --minute-tokens obcxxxxxxxxxx
# 批量(逗号分隔,最多 50 个)
lark-cli minutes +detail --as <source_identity> --minute-tokens obcxxx,obcyyy --summary --todo
# 全产物
lark-cli minutes +detail --as <source_identity> --minute-tokens obcxxx --summary --todo --chapter --keyword --transcript
# 仅逐字稿,覆盖已有文件,指定输出目录
lark-cli minutes +detail --as <source_identity> --minute-tokens obcxxx --transcript --overwrite --output-dir ./out
```
## 输出
`minutes` 数组每条含 `minute_token``title``note_id``artifacts``note_id` 仅在该妙记关联了会议纪要时返回,可直接传给 [`note +detail`](lark-note-detail.md) 拿纪要文档 token,无需再绕回 `vc +detail``artifacts` 中**只包含本次请求的产物**
| 字段 | 类型 | 说明 |
|------|------|------|
| `artifacts.summary` | string | AI 总结。 |
| `artifacts.todos` | array | 待办事项列表。 |
| `artifacts.chapters` | array | 章节列表。 |
| `artifacts.keywords` | array | 关键词列表。 |
| `artifacts.transcript_file` | string | 逐字稿本地文件路径。 |
逐字稿默认落地 `./minutes/{minute_token}/transcript.txt`,与 `minutes +download` 同目录便于聚合。指定 `--output-dir <dir>` 时改写到 `<dir>/artifact-{title}-{minute_token}/transcript.txt`
## minute_token 来源
| 来源 | 取值字段 |
|------|---------|
| 妙记 URL `https://*.feishu.cn/minutes/obcxxx` | 截路径最后一段 `obcxxx` |
| `vc +detail --meeting-ids` | `minute_token` |
| `vc +recording --meeting-ids` | `minute_token` |
| `minutes +search` | `minute_token` |
`minute_token` 不要直接传给 `note +detail`:需要关联 Note 时,先从本命令结果读取 `note_id`。跨产物流程由 [`query-minutes-and-artifacts`](../scenes/query-minutes-and-artifacts.md) 编排。
## 相关场景
- [查询妙记及其产物](../scenes/query-minutes-and-artifacts.md)
@@ -126,12 +126,10 @@ API 限流 5 次/秒,批量下载时需注意控制频率。
## 提示
- 音视频文件可能较大,下载无固定超时限制(由用户 Ctrl+C 控制取消)。
- 默认落点 `./minutes/{minute_token}/``minutes +detail` 的逐字稿共享同一目录,方便 Agent 聚合同一会议的所有产物
- 默认落点 `./minutes/{minute_token}/``minutes +detail` 的逐字稿共享同一目录,方便 Agent 聚合同一妙记的原始音视频和逐字稿
- 单 token 模式下 `--output` 若传入已存在目录(如 `--output ./existing-dir`),等价于 `--output-dir`,文件落入该目录(cp 语义)。
- 批量模式下 `--output` 不接受已存在的文件路径(会报错),应改用 `--output-dir`
- 如需获取妙记的纪要内容(逐字稿、AI 总结等),请使用 [minutes +detail](lark-minutes-detail.md)。
## 参考
- [lark-minutes](../SKILL.md) — 妙记全部命令
- [lark-minutes-detail](lark-minutes-detail.md) — 妙记详情与 AI 产物查询
## 相关场景
- [查询妙记及其产物](../scenes/query-minutes-and-artifacts.md)
@@ -117,19 +117,6 @@ CLI 会先按输入的本地日历日语义解析,再标准化为 RFC3339 时
如果用户说“昨天的妙记”“今天的妙记”“某一天内的妙记”,应把 `--start``--end` 都设置为同一天,而不是把 `--end` 设成下一天。
### 7. 会议的妙记先定位会议
如果用户明确要找某场会议的妙记,或同时提到“会议 / 开会 / 会”和“妙记”,应优先使用 `vc +search` 先定位会议,再按需通过 `vc +recording` 获取 `minute_token`,不要直接按妙记时间范围或关键词搜索。
只有在无法通过会议搜索定位目标会议,或用户明确要求按妙记维度检索时,才回退到 `minutes +search`
如果用户要的是"某场会议的妙记信息""某个日程对应的妙记详情""minute\_token""妙记链接""标题""时长""owner",正确链路是:
1. `vc +search``calendar +agenda` 先定位会议 / 日程
2. `vc +recording` 获取 `minute_token`
3. `minutes minutes get` 查询妙记基础信息
<br />
## 时间格式
`--start``--end` 支持以下时间格式:
@@ -149,7 +136,8 @@ CLI 会先按输入的本地日历日语义解析,再标准化为 RFC3339 时
- 当结果中返回 `has_more=true` 时,说明还有更多页可继续获取。
- 继续翻页时,使用响应中的 `page_token` 搭配 `--page-token` 发起下一次查询。
- 不要假设调大 `--page-size` 就能拿全结果;分页遍历时应以 `has_more``page_token` 为准。
- `has_more=true` 时,逐页累计已读取的 `items` 数:累计不到 50 条之前可自动继续翻页;超过 50 条后应停下来向用户确认是否获取全部结果。
- 用户未明确要求全量时,逐页累计已读取的 `items` 数:累计不到 50 条之前可自动继续翻页;超过 50 条且仍有更多结果时,先向用户确认是否继续获取全部结果。
- 用户明确说“全部 / 所有 / 统计 / 排序”时,该全量意图优先于 50 条确认门槛;直接按 `has_more` 翻完所有分页,按结果中的 `token` 去重后再返回、排序或统计。
```bash
# First page
@@ -159,21 +147,6 @@ lark-cli minutes +search --query "预算复盘" --page-size 20
lark-cli minutes +search --query "预算复盘" --page-size 20 --page-token '<PAGE_TOKEN>'
```
## 搜索结果中的下一步
搜索结果中的 `token` 可直接作为 `minute_token` 用于继续查询妙记产物:
通常先用搜索结果中的 `token` 获取妙记基础信息,确认描述、链接等元数据是否命中目标;只有需要进一步查看逐字稿、总结、待办、章节时,再继续查询关联的纪要产物。
如果你已经确定目标妙记,优先直接复用搜索结果中的 `token`,避免重复搜索。
```bash
# 首先查询妙记元信息(标题、时长、封面) → 用本 skill
lark-cli minutes minutes get --params '{"minute_token": "obcn***************"}'
# 查妙记关联的产物(--summary --todo --chapter --keyword --transcript 按需返回)
lark-cli minutes +detail --minute-tokens <minute_token> --summary
```
## 常见错误与排查
| 错误现象 | 根本原因 | 解决方案 |
@@ -194,8 +167,5 @@ lark-cli minutes +detail --minute-tokens <minute_token> --summary
- 排查参数与请求结构时优先使用 `--dry-run`
- 搜索的时间范围最大为 1 个月,如果需要搜索更长时间范围的妙记,需要拆分为多次时间范围为一个月查询。
## 参考
- [lark-minutes](../SKILL.md) -- 妙记相关命令
- [lark-minutes-detail](lark-minutes-detail.md) -- 基于 `minute_token` 获取逐字稿、总结、待办、章节等产物
- [lark-vc](../../lark-vc/SKILL.md) -- 视频会议全部命令
## 相关场景
- [查询妙记及其产物](../scenes/query-minutes-and-artifacts.md)
@@ -39,7 +39,7 @@
3. **解析 `--from-speaker-id`**
- 根据用户描述的原说话人(展示名,如「说话人1」「张三」),在 `speakers[]` 里按 `name` **精确匹配**,取对应的 **`speaker_id`** 作为 `--from-speaker-id` 的值。
- **`--from-speaker-id` 只传 `speaker_id`,不传展示名。**
- 若同名有多条(`name` 相同、`speaker_id` 不同):**不要擅自挑选**。可结合 [`vc +notes --minute-tokens`](../../lark-vc/references/lark-vc-notes.md) 对照各人发言内容,请用户确认后再用精确的 `speaker_id`
- 若同名有多条(`name` 相同、`speaker_id` 不同):**不要擅自挑选**。可 [`minutes +detail --transcript`](lark-minutes-detail.md) 对照各人发言内容,请用户确认后再用精确的 `speaker_id`
- 若列表中无匹配展示名:告知用户并核对拼写,或请用户在妙记页面确认标签。
4. **解析 `--to-user-id`**
@@ -102,6 +102,5 @@ Agent 必须先 `lark-cli api GET .../speakerlist`,再 `+speaker-replace``-
| `from_speaker_id` | 实际用于替换的不透明说话人标识 |
| `to_user_id` | 替换后的新说话人 open_id,与输入的 `--to-user-id` 一致 |
## 参考
- [lark-minutes](../SKILL.md) -- 妙记相关功能说明
## 相关场景
- [生成和修改妙记](../scenes/create-and-edit-minutes.md)
@@ -113,8 +113,5 @@ lark-cli minutes +summary --minute-token obcnxxxxxxxxxxxxxxxxxxxx --summary @sum
| 参数无效 | — | `minute_token` 缺失或格式错误 | 检查 token 是否完整 |
| 权限不足 | — | 缺少 `minutes:minutes:update` | 运行 `auth login --scope "minutes:minutes:update"` |
## 参考
- [lark-minutes](../SKILL.md) — 妙记全部命令
- [minutes +todo](lark-minutes-todo.md) — 替换待办项
- [minutes +detail](lark-minutes-detail.md) — 读取总结、待办等 AI 产物
## 相关场景
- [生成和修改妙记](../scenes/create-and-edit-minutes.md)
@@ -1,6 +1,6 @@
# minutes +todo
> **路由**:本命令操作**妙记内的 AI 待办**,不是飞书任务(Task)。用户说「在妙记里新建待办」时**必须**用本命令,**禁止**走 `lark-cli task` / `tasklists list` / `task +create`。详见 [lark-minutes/SKILL.md](../SKILL.md) 第 6 节
> **路由**:本命令操作**妙记内的 AI 待办**,不是飞书任务(Task)。用户说「在妙记里新建待办」时**必须**用本命令,**禁止**走 `lark-cli task` / `tasklists list` / `task +create`。详见 [生成和修改妙记](../scenes/create-and-edit-minutes.md)
对妙记中的待办做新增 / 更新 / 删除(单条或批量)。写操作。
@@ -24,17 +24,10 @@
lark-cli minutes +todo --minute-token obcnxxxxxxxxxxxxxxxxxxxx --operation add --todo "跟进预算审批" --is-done=false --as user
# 批量:一次新增两条
lark-cli minutes +todo --minute-token obcnxxxxxxxxxxxxxxxxxxxx --as user --todos '[
{"operation":"add","content":"晚上好1","is_done":true},
{"operation":"add","content":"晚上好2","is_done":false}
]'
lark-cli minutes +todo --minute-token obcnxxxxxxxxxxxxxxxxxxxx --as user --todos '[{"operation":"add","content":"晚上好1","is_done":true},{"operation":"add","content":"晚上好2","is_done":false}]'
# 批量:混合增删改
lark-cli minutes +todo --minute-token obcnxxxxxxxxxxxxxxxxxxxx --as user --todos '[
{"operation":"add","content":"新待办","is_done":false},
{"operation":"update","todo_id":"1234567890","content":"已更新","is_done":true},
{"operation":"delete","todo_id":"9876543210"}
]'
lark-cli minutes +todo --minute-token obcnxxxxxxxxxxxxxxxxxxxx --as user --todos '[{"operation":"add","content":"新待办","is_done":false},{"operation":"update","todo_id":"1234567890","content":"已更新","is_done":true},{"operation":"delete","todo_id":"9876543210"}]'
# 从文件读取
lark-cli minutes +todo --minute-token obcnxxxxxxxxxxxxxxxxxxxx --as user --todos @todos.json
@@ -129,8 +122,5 @@ lark-cli minutes +todo --minute-token obcnxxxxxxxxxxxxxxxxxxxx --operation add -
| `error.subtype` = `permission_denied` | **妙记资源无编辑权**:向妙记所有者申请该妙记的编辑/协作权限;**不要**走 `auth login --scope` |
| 缺少 OAuth scope`error.missing_scopes``minutes:minutes:update` | `lark-cli auth login --scope "minutes:minutes:update"` |
## 参考
- [lark-minutes](../SKILL.md)
- [minutes +summary](lark-minutes-summary.md)
- [minutes +detail](lark-minutes-detail.md)
## 相关场景
- [生成和修改妙记](../scenes/create-and-edit-minutes.md)
@@ -34,6 +34,5 @@ lark-cli minutes +update --minute-token xxx --topic "周会纪要 2026-05-18"
| `minute_token` | 被修改的妙记 Token,与输入的 `--minute-token` 一致,可继续用于查询妙记信息、下载媒体或获取纪要产物 |
| `topic` | 修改后的妙记标题,与输入的 `--topic` 一致 |
## 参考
- [lark-minutes](../SKILL.md) -- 妙记相关功能说明
## 相关场景
- [生成和修改妙记](../scenes/create-and-edit-minutes.md)
@@ -0,0 +1,65 @@
# minutes +upload
上传音视频文件到飞书妙记并生成妙记(Minute)。
本 skill 对应 shortcut`lark-cli minutes +upload`
## 典型触发表达
- "把这个音视频文件转成妙记"
- "把这个音视频文件转成纪要"
- "把这个音视频文件转成逐字稿、文字稿或撰写文字"
- "把这个音视频文件转成总结、待办或章节"
## 命令示例
```bash
# 通过已上传到云空间(云盘/云存储)的 file_token 生成妙记
lark-cli minutes +upload --file-token boxcnxxxxxxxxxxxxxxxx
```
## 参数
| 参数 | 必填 | 说明 |
|------|------|------|
| `--file-token <token>` | 是 | 已经上传到飞书云空间(云盘/云存储)的音视频文件的 file_token |
## 支持的格式与限制
待上传到妙记的原始音视频文件必须满足以下要求:
- 支持音频格式:`wav``mp3``m4a``aac``ogg``wma``amr`
- 支持视频格式:`avi``wmv``mov``mp4``m4v``mpeg``ogg``flv`
- 音视频时长不能超过 `6` 小时
- 文件大小不能超过 `6 GB`
> 说明:本 shortcut 只接收 `file_token`,不会直接读取本地文件内容,因此这些格式、时长和大小限制对应的是**原始上传文件**本身。若妙记生成失败,请先回查源文件是否满足上述要求。
## 核心约束
### 1. 必须提供 file_token
本接口不直接处理本地文件的上传,必须先使用 `drive +upload` 将文件上传到云空间(云盘/云存储)获取 `file_token`,然后再调用本接口。
### 2. 异步生成
API 会立即返回 `minute_url`,但妙记可能仍在异步生成中。`minutes +upload` 不返回处理状态,命令成功只表示异步创建请求已提交;只有后续执行 `minutes +detail` 并确认就绪,才能声称妙记产物已生成或可用。上传与后续产物获取由 [`create-and-edit-minutes`](../scenes/create-and-edit-minutes.md) 编排;上传后立即查询产物时,`minutes +detail` 必须使用 `--wait-ready`
## 输出结果示例
```json
{
"minute_url": "http(s)://<host>/minutes/<minute-token>",
"minute_token": "<minute-token>"
}
```
| 字段 | 说明 |
|------|------|
| `minute_url` | 生成的妙记访问链接 |
| `minute_token` | 从 `minute_url` 提取出的妙记 Token,可直接传给 `minutes +detail --minute-tokens` |
## 相关场景
- [生成和修改妙记](../scenes/create-and-edit-minutes.md)
@@ -0,0 +1,15 @@
# note +detail
通过 `note_id` 查询会议纪要详情,获取下挂文档 Token(AI 智能纪要、逐字稿、会中共享文档)。只读,支持 `--as user``--as bot`
## 命令
```bash
lark-cli note +detail --note-id <note_id>
lark-cli note +detail --note-id <note_id> --as bot
```
`note_id` 由其他命令取得时,必须显式沿用来源身份。应用身份能否读到数据取决于应用对纪要主文档的查看权限。若 `--as bot` 返回 `note_display_type=unified`,不要静默切换到用户身份执行 `note +transcript`;先向用户说明该命令仅支持用户身份。
## 相关场景
- [基于 note_id 查询纪要、逐字稿、共享文档等](../scenes/query-note-and-artifacts.md)
@@ -0,0 +1,19 @@
# note +transcript
只在 `note +detail` 已确认 `note_display_type=unified` 时使用。普通纪要逐字稿是独立 Docx 文档,应回到 [lark-doc](../../lark-doc/SKILL.md) 读取 `verbatim_doc_token`
`note +transcript` 仅支持 `--as user`,不支持 `--as bot`。如果 `note +detail --as bot` 返回 `unified`,不要静默省略 `--as` 或改用用户身份继续;先说明该限制,只有用户明确同意后才切换身份重试。
```bash
lark-cli note +transcript --note-id <note_id>
```
## 行为契约
- CLI 会先校验该 Note 是否为 `unified`;不是 unified 时不拉取 transcript。
- CLI 内部自动翻页并拼接完整内容;任一页失败时整体报错,不保存半截 transcript。
- 默认保存到 `./notes/{note_id}/unified_transcript.md``--transcript-format plain_text` 时保存为 `.txt`
- 目标文件已存在时会失败;用户明确要覆盖时才加 `--overwrite`
## 相关场景
- [基于 note_id 查询纪要、逐字稿、共享文档等](../scenes/query-note-and-artifacts.md)
@@ -5,25 +5,13 @@
本 skill 对应 shortcut`lark-cli vc +meeting-join`(调用 `POST /open-apis/vc/v1/bots/join`)。
> **不要把 9 位会议号等同于入会意图。** 用户给出 9 位会议号并询问“会议讲了什么 / 查会中事件”时,先用 `+meeting-list-active` 查当前 active meetings 并按 `meeting_no` 匹配;只有用户明确要求“入会 / 让应用机器人旁听 / 代我参会”时才调用本命令。
> **不要把 9 位会议号等同于入会意图。** 用户给出 9 位会议号并询问“会议讲了什么 / 查会中事件”时,先用 `vc +meeting-list-active` 查当前 active meetings 并按 `meeting_no` 匹配;只有用户明确要求“入会 / 让应用机器人旁听 / 代我参会”时才调用本命令。
## 命令
```bash
# 仅指定会议号(无密码)
lark-cli vc +meeting-join --as bot --meeting-number 123456789
# 指定会议号 + 密码
lark-cli vc +meeting-join --as bot --meeting-number 123456789 --password 8888
# 从邀请事件透传 call_id(参见「如何获取输入参数」)
lark-cli vc +meeting-join --as bot --meeting-number 123456789 --call-id a08e06bf-9a41-44e4-a89c-a7871899e783
# 输出格式
lark-cli vc +meeting-join --as bot --meeting-number 123456789 --format json
# 预览 API 调用(不实际加入会议)
lark-cli vc +meeting-join --as bot --meeting-number 123456789 --dry-run
```
## 参数
@@ -81,36 +69,6 @@ lark-cli vc +meeting-join --as bot --meeting-number 123456789 --dry-run
| `password` | 若会议设置了入会密码,由主持人提供 |
| `call-id` | 由 `vc.bot.meeting_invited_v1` 邀请事件的 `call_id` 字段携带,Agent 收到事件时透传过来;无邀请事件场景(如 Agent 主动入会)不传 |
## Agent 组合场景
### 场景 1:加入会议 → 监听会中事件
```bash
# 第 1 步:加入会议,记录返回的 meeting.id
lark-cli vc +meeting-join --as bot --meeting-number 123456789
# 第 2 步:使用返回的 meeting.id 查询会中事件
lark-cli vc +meeting-events --as bot --meeting-id <meeting.id> --page-all --format pretty
```
如果 bot 已经在会中,也可以通过 active meeting 找回 `meeting_id`
```bash
lark-cli vc +meeting-list-active --as bot --user-id <user_open_id> --format json
```
### 场景 2:加入会议 → 会后进入 lark-vc 获取会议产物信息
```bash
# 第 1 步:加入并参会
lark-cli vc +meeting-join --as bot --meeting-number 123456789
# 第 2 步:会议结束后,先查询会议产物
lark-cli vc +detail --meeting-ids <meeting.id>
```
后续按 `lark-vc` 的产物决策处理:根据 `note_display_type``note_id``minute_token` 和用户意图选择纪要正文、逐字稿或妙记。
## 常见错误与排查
| 错误现象 | 根本原因 | 解决方案 |
@@ -119,7 +77,7 @@ lark-cli vc +detail --meeting-ids <meeting.id>
| 会议密码错误 | `--password` 错误或未提供 | 向主持人确认会议密码 |
| 会议不存在 / 已结束 | 会议号错误或会议未进行中 | 确认会议正在进行中 |
| `HTTP 403: no permission` / `121003` | 入会前置条件不满足,通常不是单纯 scope 问题 | 依次确认:1)会议允许智能体加入;2)会议号正确;3)如有密码,已正确传入 `--password`;4)会议已开始;5)等候室 / 入会审批已放行;6)会议未禁止当前身份加入(如限制外部、限制应用机器人、仅特定成员可入会);确认后重试 |
| 应用身份权限不足 | 应用权限、租户安装权限可访问的数据范围或 VC Agent privilege 未配置完整 | 不要执行 `auth login`。以 CLI 返回的 metadata / error envelope 为准确认缺失权限;检查应用发布/安装,以及开放平台“权限可访问的数据范围”:选择“按条件筛选”,条件为“会议的归属者 包含 与应用的可用范围一致”;仍失败再排查内测 privilege / 灰度 |
| 应用身份权限不足 | 应用权限、租户安装权限可访问的数据范围未配置完整 | 不要执行 `auth login`。以 CLI 返回的 metadata / error envelope 为准确认缺失权限;检查应用发布/安装,以及开放平台“权限可访问的数据范围”:选择“按条件筛选”,条件为“会议的归属者 包含 与应用的可用范围一致”;配置正确仍失败时,保留错误码和 `log_id`,按服务端权限异常排查 |
| 入会被拒绝 | 等候室 / 入会审批 / 限制外部入会 | 联系主持人放行或调整会议设置 |
## 提示
@@ -128,14 +86,5 @@ lark-cli vc +detail --meeting-ids <meeting.id>
- 入会会让机器人立即出现在参会列表;若用户要求退出 / 离开 / 结束参会,直接使用 `+meeting-leave --as bot --meeting-id <meeting.id>`。参数格式不确定时可选 `--dry-run` 预览,但不是必经步骤。
- 执行成功后,立即记录返回的 `meeting.id`,用于后续 `+meeting-leave` / `+meeting-events`
## 参考
- [lark-vc-agent-meeting-leave](lark-vc-agent-meeting-leave.md) — 对应的离会命令
- [lark-vc-meeting-list-active](../../lark-vc/references/lark-vc-meeting-list-active.md) — 发现当前可读事件的进行中会议 ID
- [lark-vc-meeting-events](../../lark-vc/references/lark-vc-meeting-events.md) — 会中事件流
- [lark-vc-search](../../lark-vc/references/lark-vc-search.md) — 搜索历史会议记录
- [lark-vc-recording](../../lark-vc/references/lark-vc-recording.md) — 查询 minute_token
- [lark-vc-detail](../../lark-vc/references/lark-vc-detail.md) — 获取会议详情
- [lark-vc-agent](../SKILL.md) — Agent 参会能力(本 skill
- [lark-vc](../../lark-vc/SKILL.md) — 视频会议原子域(Meeting / Note 等核心概念)
- [lark-shared](../../lark-shared/SKILL.md) — 认证和全局参数
## 相关场景
- [应用机器人参会与会中互动](../scenes/live-meeting-attend.md)
@@ -10,12 +10,6 @@
```bash
# 通过 meeting_id 离会
lark-cli vc +meeting-leave --as bot --meeting-id 69xxxxxxxxxxxxx28
# 输出格式
lark-cli vc +meeting-leave --as bot --meeting-id 69xxxxxxxxxxxxx28 --format json
# 预览 API 调用(不实际离会)
lark-cli vc +meeting-leave --as bot --meeting-id 69xxxxxxxxxxxxx28 --dry-run
```
## 参数
@@ -54,30 +48,6 @@ lark-cli vc +meeting-leave --as bot --meeting-id 69xxxxxxxxxxxxx28 --dry-run
|---------|---------|
| `meeting-id` | `+meeting-join --as bot` 返回的 `meeting.id`;或应用身份 `+meeting-list-active --as bot --user-id <user_open_id>` 返回的 `meeting_id` |
## Agent 组合场景
### 场景 1:加入 → 用户明确要求时离开
```bash
# 第 1 步:加入会议,记录 meeting.id
lark-cli vc +meeting-join --as bot --meeting-number 123456789
# 第 2 步:在会中处理用户请求(如监听发言、记录信息等)
# ...
# 第 3 步:仅在用户明确要求退出 / 离开 / 结束参会时,使用上一步记录的 meeting.id 离会
lark-cli vc +meeting-leave --as bot --meeting-id <meeting.id>
```
### 场景 2:会后补拉产物(不需要离会)
如果用户只是要求会议结束后拉录制、纪要或逐字稿,不要先调用 `+meeting-leave`;直接跨到 `lark-vc` 查询会后产物。
```bash
# 第 1 步:会议结束后进入 lark-vc 获取会议产物信息
lark-cli vc +detail --meeting-ids <meeting.id>
```
## 常见错误与排查
| 错误现象 | 根本原因 | 解决方案 |
@@ -92,14 +62,5 @@ lark-cli vc +detail --meeting-ids <meeting.id>
- `+meeting-leave` 优先使用 `+meeting-join --as bot` 返回的 `meeting.id`,但不是每次 join 后都必须调用 leave。
- `meeting_id` 如果来自 `+meeting-list-active`,必须来自应用身份,并确认应用机器人就在该会议中。不要用 9 位会议号。
## 参考
- [lark-vc-agent-meeting-join](lark-vc-agent-meeting-join.md) — 对应的入会命令
- [lark-vc-meeting-list-active](../../lark-vc/references/lark-vc-meeting-list-active.md) — 发现当前可读事件的进行中会议 ID
- [lark-vc-meeting-events](../../lark-vc/references/lark-vc-meeting-events.md) — 会中事件流
- [lark-vc-search](../../lark-vc/references/lark-vc-search.md) — 搜索历史会议(获取 meeting_id)
- [lark-vc-recording](../../lark-vc/references/lark-vc-recording.md) — 查询 minute_token
- [lark-vc-detail](../../lark-vc/references/lark-vc-detail.md) — 获取会议详情
- [lark-vc-agent](../SKILL.md) — Agent 参会能力(本 skill
- [lark-vc](../../lark-vc/SKILL.md) — 视频会议原子域(Meeting / Note 等核心概念)
- [lark-shared](../../lark-shared/SKILL.md) — 认证和全局参数
## 相关场景
- [应用机器人参会与会中互动](../scenes/live-meeting-attend.md)
@@ -0,0 +1,31 @@
# vc +detail
通过会议 ID 获取会议详情,包括基本信息、关联的纪要 ID(`note_id`)和妙记 Token`minute_token`)。只读,支持 `--as user` / `--as bot`
## 命令
```bash
# 单个 / 批量(逗号分隔,最多 50 个)
lark-cli vc +detail --meeting-ids <meeting_id1>,<meeting_id2>
# 应用身份(只能查应用有权限的会议)
lark-cli vc +detail --meeting-ids <meeting_id1>,<meeting_id2> --as bot
```
## 输出字段
| 字段 | 说明 |
|------|------|
| `meeting_id` | 会议 ID |
| `meeting_no` | 会议 9 位号码 |
| `topic` | 会议主题 |
| `start_time` | 开始时间 |
| `end_time` | 结束时间 |
| `note_id` | 关联的纪要 ID。 |
| `minute_token` | 关联的妙记 Token。 |
跨产物选择和后续命令链由 [`query-meeting-and-artifacts`](../scenes/query-meeting-and-artifacts.md) 统一编排。`note_id` / `minute_token` 由本命令取得后,后续 `note +detail``minutes +detail` 和 Doc 读取命令必须显式沿用同一个 `--as`
## 相关场景
- [查询会议及其产物](../scenes/query-meeting-and-artifacts.md)
@@ -56,31 +56,7 @@ lark-cli vc +meeting-events --as <same_identity> --meeting-id <id> --page-token
- 应用身份路径:应用机器人必须在会中或参会过;不要拿任意 `meeting_id` 直接查。
- 不要在拿到 `meeting_id` 后随意切换身份。身份不一致时,常见结果是空列表、`no permission``bot is not in meeting`
### 3. 读取事件前必须先拿到可见的 meeting_id
最稳妥的调用顺序通常是:
```bash
# 方式 1:先入会,直接记录返回的 meeting.id
lark-cli vc +meeting-join --as bot --meeting-number 123456789
# 再查询事件
lark-cli vc +meeting-events --as bot --meeting-id <id> --page-all --format pretty
```
如果应用机器人已经在会中,也可以先通过 active meeting 找会:
```bash
lark-cli vc +meeting-list-active --as bot --user-id <user_open_id> --format json
lark-cli vc +meeting-events --as bot --meeting-id <id> --page-all --format pretty
```
如果要查询当前登录用户所在会议:
```bash
lark-cli vc +meeting-list-active --as user --format json
lark-cli vc +meeting-events --as user --meeting-id <id> --page-all --format pretty
```
### 3. 应用身份的可见性窗口
若应用机器人已离会、未入会、或会议已经无法再判断身份,后端通常会报:
- `bot is not in meeting, no permission`
@@ -110,8 +86,8 @@ lark-cli vc +meeting-events --as user --meeting-id <id> --page-all --format pret
### 5. 输出格式差异
- `--format json`:结构化契约,顶层包含 `meeting``identity``events``has_more``page_token``identity` 表示当前读取身份;事件 actor 统一含 `participant_type``role``label`;每条事件保留 `payload` 便于追溯细节。
- `--format pretty`:默认推荐格式,输出当前身份和逐条时间线,适合快速理解“发生了什么”。
- `--format json`:结构化契约,顶层包含 `meeting``identity``events``has_more``page_token``identity` 表示当前读取身份;事件 actor 统一含 `participant_type``role``label`;每条事件保留 `payload` 便于追溯细节。
- `--format ndjson`:输出事件行,并带 metadata 行,适合流式消费。
**选型原则**:默认先用 `--format pretty`;仅当 `pretty` 缺少完成任务所必需的结构化字段时,才改用 `--format json`。用户明确要求 JSON 或规则明确要求结构化字段时可直接用 `--format json`;需要流式消费时用 `--format ndjson`
@@ -324,74 +300,16 @@ lark-cli vc +meeting-events \
| `start` / `end` | 用户给出的时间范围;如未给出则默认取全量可见事件 |
| `page-token` | 上一页或上一次查询结果中保存的 `page_token`;建议持久化保存,便于下次继续拉取新增事件 |
## Agent 组合场景
### 场景 1:入会后读取会中发生了什么
```bash
# 第 1 步:加入会议,记录返回的 meeting.id
JOIN=$(lark-cli vc +meeting-join --as bot --meeting-number 123456789 --format json)
MID=$(echo "$JOIN" | jq -r '.data.meeting.id')
# 第 2 步:用 meeting.id 读取当前可见事件
lark-cli vc +meeting-events --as bot --meeting-id "$MID" --page-all --format pretty
```
### 场景 1b:应用机器人已在会中,先发现 meeting_id 再读事件
```bash
lark-cli vc +meeting-list-active --as bot --user-id <user_open_id> --format json
lark-cli vc +meeting-events --as bot --meeting-id <id> --page-all --format pretty
```
### 场景 1c:当前登录用户正在会中,先发现 meeting_id 再读事件
```bash
lark-cli vc +meeting-list-active --as user --format json
lark-cli vc +meeting-events --as user --meeting-id <id> --page-all --format pretty
```
### 场景 2:过滤某段时间内的事件
```bash
lark-cli vc +meeting-events \
--as <same_identity> \
--meeting-id <id> \
--start 2026-04-17T15:00:00+08:00 \
--end 2026-04-17T16:00:00+08:00 \
--page-all \
--format pretty
```
### 场景 3:基于上一次的 `page_token` 继续查新增事件
```bash
# 上一次查询结束后,保留最后返回的 page_token
# 这次直接从该游标继续拉新增事件
lark-cli vc +meeting-events \
--as <same_identity> \
--meeting-id <id> \
--page-token <last_page_token> \
--page-all \
--format pretty
```
适用规则:
- 当用户说“继续看新事件”“看上次之后新增了什么”时,优先使用上一次保存的 `page_token`
- 如果这次返回里仍有 `has_more=true`、pretty 里出现 `more available`,或又返回了新的 `page_token`,说明新增事件还没拉完,应继续分页,而不是把当前页误当成完整增量结果。
- 只有在用户明确要求“从头回放全部事件”时,才忽略已有 `page_token`,重新从第一页开始。
## 常见错误与排查
| 错误现象 | 根本原因 | 解决方案 |
|---------|---------|---------|
| `--meeting-id is required` | 未传入 `--meeting-id` | 传入长数字 `meeting.id` |
| `10005 bot is not in meeting` | 使用应用身份读取,但应用机器人从未真实入会该会议;或会议已结束但应用机器人从未在会中出现过 | 如果 `meeting_id` 来自用户身份发现,改回 `--as user`;如果确实要应用身份读取,先让应用机器人入会或确认它曾参会后再用 `--as bot`。**如果只是想看参会人快照,改用 `lark-cli vc meeting get --params '{"meeting_id":"<meeting.id>"}' --with-participants`** |
| `10005 bot is not in meeting` | 使用应用身份读取,但应用机器人从未真实入会该会议;或会议已结束但应用机器人从未在会中出现过 | 如果 `meeting_id` 来自用户身份发现,改回 `--as user`;如果确实要应用身份读取,先让应用机器人入会或确认它曾参会后再用 `--as bot`。**如果只是想看参会人快照,改用 `lark-cli vc meeting get --params '{"meeting_id":"<meeting.id>","with_participants":true}'`** |
| 用户身份无权限 / 不可见 | 当前用户不是该会议的可见参与者,或 `meeting_id` 不是从用户身份路径获得 | 不要反复执行 `auth login`。先确认 `meeting_id` 是否来自 `+meeting-list-active --as user`;如果用户明确要切到应用身份,再通过 `+meeting-list-active --as bot --user-id <user_open_id>` 获取应用身份可读的 `meeting_id`,或在用户明确同意后让应用机器人入会,再用 `+meeting-events --as bot` 读取 |
| `20001 meeting_status_MEETING_END` | 会议已结束且已超出后端允许的 5 分钟宽限窗口 | 本接口不再适合继续拉取事件。先用 `lark-cli vc +detail --meeting-ids <meeting.id>` 获取会议产物信息,再根据 `note_display_type` / `note_id` / `minute_token` 和用户意图选择纪要正文、逐字稿或妙记;参会人请用 `lark-cli vc meeting get --params '{"meeting_id":"<meeting.id>"}' --with-participants` |
| `20002 meeting not exist` | `meeting_id` 错误,或会议实例当前已不可获取(常见于把 9 位会议号当 meeting_id 传) | 确认传入的是长数字 `meeting_id`,不是 9 位会议号 |
| 应用身份权限不足 | 应用权限、租户安装权限可访问的数据范围或 VC Agent privilege 未配置完整 | 不要执行 `auth login`。请应用开发者开通 `vc:meeting.bot.join:write`;再检查应用发布/安装和权限可访问的数据范围,均正确仍失败时再排查内测灰度权限 |
| 应用身份权限不足 | 应用权限、租户安装权限可访问的数据范围未配置完整 | 不要执行 `auth login`。请应用开发者开通 `vc:meeting.bot.join:write`;再检查应用发布/安装和权限可访问的数据范围;配置正确仍失败时,保留错误码和 `log_id`,按服务端权限异常排查 |
| `HTTP 404` / `HTTP 500` | 服务端当前无法找到或处理该会议实例 | 换一个正在进行且 bot 可见的 meeting_id,或排查后端问题 |
## 提示
@@ -399,18 +317,10 @@ lark-cli vc +meeting-events \
- 这是**会中事件流**查询,不适合拿来搜历史会议记录;搜历史会议请用 `+search`
- 如果会议已经结束,不要卡在 `+meeting-events`
- 先用 `lark-cli vc +detail --meeting-ids <meeting.id>` 获取会议产物信息。
- 再根据 `note_display_type``note_id``minute_token` 和用户意图,按 `lark-vc` 的产物决策读取纪要正文、逐字稿或妙记。
- 再根据 `note_display_type``note_id``minute_token` 和用户意图,按 `lark-meeting` 的产物决策读取纪要正文、逐字稿或妙记。
- 事件列表是否完整,取决于应用机器人何时入会、何时离会,以及后端当前可见的会中事件范围。对于已结束会议,通常只在**结束后 5 分钟内**、且应用机器人**曾经在会中**时还能继续拉到事件。
- 查询"谁参加过某会议"请用 `vc meeting get --params '{"meeting_id":"<id>","with_participants":true}'`——这是参会人**快照** API,不依赖 bot 是否参会,对已结束会议也可查;**不要** 用 `+meeting-events` 做参会人查询。
## 参考
- [lark-vc-agent-meeting-join](../../lark-vc-agent/references/lark-vc-agent-meeting-join.md) — 先真实入会
- [lark-vc-meeting-list-active](lark-vc-meeting-list-active.md) — 发现当前可读事件的进行中会议 ID
- [lark-vc-agent-meeting-leave](../../lark-vc-agent/references/lark-vc-agent-meeting-leave.md) — 用户明确要求时离会
- [lark-vc-search](lark-vc-search.md) — 搜索历史会议(获取 meeting_id)
- [lark-vc-recording](lark-vc-recording.md) — 查询 minute_token
- [lark-vc-detail](lark-vc-detail.md) — 获取会议详情
- [lark-vc-agent](../../lark-vc-agent/SKILL.md) — Agent 参会能力
- [lark-vc](../SKILL.md) — 视频会议原子域(Meeting / Note 等核心概念)
- [lark-shared](../../lark-shared/SKILL.md) — 认证和全局参数
## 相关场景
- [会中事件与会中互动](../scenes/live-meeting-interact.md)
- [应用机器人参会与会中互动](../scenes/live-meeting-attend.md)
@@ -33,22 +33,6 @@ lark-cli vc +meeting-list-active --as bot --user-id ou_xxx --format json
应用身份返回空,不代表目标用户不在任何会议中,只能说明没有找到“目标用户在会中且应用机器人也在会中”的当前会。
常见流程:
```bash
# 方式 1:先让应用机器人入会,直接从 join 响应拿 meeting.id
lark-cli vc +meeting-join --as bot --meeting-number 123456789 --format json
lark-cli vc +meeting-events --as bot --meeting-id <id> --page-all --format pretty
# 方式 2:应用机器人已经在会中时,用应用身份发现 meeting_id
lark-cli vc +meeting-list-active --as bot --user-id <user_open_id> --format json
lark-cli vc +meeting-events --as bot --meeting-id <id> --page-all --format pretty
# 方式 3:查询当前登录用户所在会议发生了什么
lark-cli vc +meeting-list-active --as user --format json
lark-cli vc +meeting-events --as user --meeting-id <id> --page-all --format pretty
```
## 多会议选择
- 如果返回多个会议,不要自动挑第一个。
@@ -59,14 +43,6 @@ lark-cli vc +meeting-events --as user --meeting-id <id> --page-all --format pret
用户提供 9 位会议号但没有明确要求应用机器人入会时,把会议号当作 active meeting 的筛选条件,而不是写操作指令。
```bash
# 用户问“我当前这个会讲了什么”
lark-cli vc +meeting-list-active --as user --format json
# 用户问“让应用机器人所在/可见的这个会讲了什么”
lark-cli vc +meeting-list-active --as bot --user-id <user_open_id> --format json
```
匹配规则:
- 在返回会议中匹配 `meeting_no == <9位会议号>`
@@ -83,9 +59,8 @@ lark-cli vc +meeting-list-active --as bot --user-id <user_open_id> --format json
| 用户身份无权限 / 不可见 | 当前登录用户没有可见的进行中会议,或当前身份无法读取该会议 | 不要反复执行 `auth login`。确认用户是否在会中、是否切错 profile;用户明确要查询应用机器人可见的会议时,再拿目标用户 open_id 执行 `+meeting-list-active --as bot --user-id <user_open_id>` |
| 应用身份返回空列表 | 没有满足“目标用户在会中且应用机器人也在会中”的当前会 | 先让应用机器人入会,或确认 `user_id` 和会议状态 |
| `--user-id` 格式错误 | 传入了 internal user_id 或其他非 `ou_...` 值 | 改传目标用户 open_id |
| 应用身份权限不足 | 应用权限、租户安装权限可访问的数据范围或 VC Agent privilege 未配置完整 | 不要执行 `auth login`。请应用开发者开通 `vc:meeting.bot.join:write`;再检查应用发布/安装和权限可访问的数据范围,均正确仍失败时再排查内测灰度权限 |
| 应用身份权限不足 | 应用权限、租户安装权限可访问的数据范围未配置完整 | 不要执行 `auth login`。请应用开发者开通 `vc:meeting.bot.join:write`;再检查应用发布/安装和权限可访问的数据范围;配置正确仍失败时,保留错误码和 `log_id`,按服务端权限异常排查 |
## 参考
- [lark-vc-agent-meeting-join](../../lark-vc-agent/references/lark-vc-agent-meeting-join.md) — 让应用机器人真实入会并拿 `meeting.id`
- [lark-vc-meeting-events](lark-vc-meeting-events.md) — 使用 `meeting_id` 读取会中事件
## 相关场景
- [会中事件与会中互动](../scenes/live-meeting-interact.md)
- [应用机器人参会与会中互动](../scenes/live-meeting-attend.md)
@@ -127,8 +127,6 @@ VC_CanNotSee, VC_NoSound, VC_LooksGood, VC_SoundsClear
应用身份权限错误时,不要引导用户反复 `auth login`。按主 skill 的“应用身份权限配置检查”处理。
## 相关
- [lark-vc-meeting-list-active](lark-vc-meeting-list-active.md) — 发现当前进行中会议 ID
- [lark-vc-meeting-events](lark-vc-meeting-events.md) — 读取会中事件
- [lark-vc-agent-meeting-join](../../lark-vc-agent/references/lark-vc-agent-meeting-join.md) — 应用机器人入会
## 相关场景
- [会中事件与会中互动](../scenes/live-meeting-interact.md)
- [应用机器人参会与会中互动](../scenes/live-meeting-attend.md)
@@ -42,9 +42,7 @@ lark-cli vc +recording --meeting-ids 69xxxxxxxxxxxxx28 --dry-run
### 2. 身份支持
`--meeting-ids``--calendar-event-ids` 两种模式都支持 `--as user` `--as bot`user token 只能查自己有权限的录制;bot 使用 tenant_access_token,只能查 bot 有权限的录制
拿到的 `minute_token` 是在某个身份下解析出来的:下一步传给 `minutes minutes get` / `minutes +detail` / `minutes +download` 时必须显式沿用同一个 `--as`,不要省略让身份被 profile 默认值悄悄换掉(完整规则见 [lark-shared](../../lark-shared/SKILL.md) 的「身份延续」)。
`--meeting-ids``--calendar-event-ids` 都支持 `--as user` / `--as bot`用户身份只能查自己有权限的录制;应用身份只能查应用有权限的录制。拿到 `minute_token` 后,传给 `minutes minutes get``minutes +detail``minutes +download` 时必须显式沿用同一个 `--as`
### 3. 批量上限
@@ -74,62 +72,6 @@ lark-cli vc +recording --meeting-ids 69xxxxxxxxxxxxx28 --dry-run
| `meeting_id` | 使用 `lark-cli vc +search` 搜索历史会议,取结果中的 `id` 字段 |
| `calendar_event_id` | 使用 `lark-cli calendar +agenda` 查看日程,取结果中的 `event_id` 字段 |
## Agent 组合场景
### 场景 1:知道 meeting_id,想下载录制
```bash
# 第 1 步:通过 meeting_id 查询录制,拿到 minute_token
lark-cli vc +recording --meeting-ids xxx --as bot
# 第 2 步:使用上一步返回的 minute_token 下载妙记文件,沿用第 1 步的身份
lark-cli minutes +download --minute-tokens obcnxxxxxxxxxxxxxxxxxxxx --as bot
```
### 场景 2:知道 meeting_id,想查询妙记基础信息
```bash
# 第 1 步:通过 meeting_id 查询录制,拿到 minute_token
lark-cli vc +recording --meeting-ids xxx
# 第 2 步:使用上一步返回的 minute_token 查询妙记基础信息
lark-cli minutes minutes get --params '{"minute_token":"<minute_token>"}'
```
### 场景 3:知道 meeting_id,想获取完整纪要(含 AI 产物)
```bash
# 第 1 步:通过 meeting_id 查询录制,拿到 minute_token
lark-cli vc +recording --meeting-ids xxx
# 第 2 步:使用上一步返回的 minute_token 获取完整纪要
# ⚠️ 必须显式指定要获取的产物 flag--summary, --keyword, --todo, --chapter, --transcript
lark-cli minutes +detail --minute-tokens <minute_token> --summary --todo --chapter --transcript
```
### 场景 4:先搜索会议,再获取录制并下载
```bash
# 第 1 步:搜索历史会议,拿到 meeting_ids
lark-cli vc +search --query "周会" --start 2026-03-10
# 第 2 步:使用上一步返回的 meeting_ids 查询录制,拿到 minute_tokens
lark-cli vc +recording --meeting-ids <ids>
# 第 3 步:使用其中一个 minute_token 下载妙记文件
lark-cli minutes +download --minute-tokens <token>
```
### 场景 5:从日历事件获取录制
```bash
# 第 1 步:通过日历 event_id 查询录制,拿到 minute_token
lark-cli vc +recording --calendar-event-ids <event_id>
# 第 2 步:使用上一步返回的 minute_token 下载妙记文件
lark-cli minutes +download --minute-tokens <minute_token>
```
## 常见错误与排查
| 错误现象 | 根本原因 | 解决方案 |
@@ -147,8 +89,5 @@ lark-cli minutes +download --minute-tokens <minute_token>
- `minute_token` 从录制 URL 尾段解析(`https://meetings.feishu.cn/minutes/{minute_token}`)。
- 拿到 `minute_token` 后,如果要妙记基础信息,优先传给 `minutes minutes get`;如果要下载媒体文件,传给 `minutes +download`;如果要逐字稿、总结、待办、章节,再传给 `minutes +detail --minute-tokens`
## 参考
- [lark-vc](../SKILL.md) — 视频会议全部命令
- [lark-vc-search](lark-vc-search.md) — 搜索历史会议(获取 meeting_id)
- [lark-minutes-detail](../../lark-minutes/references/lark-minutes-detail.md) — 获取会议纪要
## 相关场景
- [查询会议及其产物](../scenes/query-meeting-and-artifacts.md)
@@ -5,7 +5,7 @@
## 关键词使用边界
`--query` 只用于真实会议关键词,例如会议主题、项目名、评审名、客户名。用户只是说"我这月参加的所有视频会议"、"最近两周我组织的所有视频会议"、"总结主要议题 / 看看参会情况"时,本质是历史会议列表和后续总结,不要把"回顾"、"所有视频会议"、"总结主要议题"等动作词放进 `--query`。这类请求应先用时间范围 + `--participant-ids` / `--organizer-ids` 搜全量候选,再按结果继续取纪要或录制信息。
`--query` 只用于 9 位会议号或真实会议关键词,例如会议主题、项目名、评审名、客户名。用户只是说"我这月参加的所有视频会议"、"最近两周我组织的所有视频会议"、"总结主要议题 / 看看参会情况"时,本质是历史会议列表和后续总结,不要把"回顾"、"所有视频会议"、"总结主要议题"等动作词放进 `--query`。这类请求应先用时间范围 + `--participant-ids` / `--organizer-ids` 搜全量候选,再按结果继续取纪要或录制信息。
列表阶段只负责找会议记录;总结阶段必须继续取证。若用户要求"主要议题"、"主要决策"、"参会情况",先确认搜索结果的 `meeting_id`、时间、组织者/参与者符合过滤条件,然后用 `vc +detail``minutes` 读取纪要、妙记或录制信息。没有纪要或妙记时,如实说明只能基于会议标题/参会数据汇总,不要编造议题。
@@ -26,6 +26,9 @@
# 关键词搜索
lark-cli vc +search --query "周会"
# 通过 9 位会议号查询会议 ID
lark-cli vc +search --query "123456789" --format json --as user
# 查询某一天开过的会(单日查询时,start 和 end 必须填写同一天)
lark-cli vc +search --start 2026-03-10 --end 2026-03-10
@@ -48,7 +51,7 @@ lark-cli vc +search --query "周会" --page-token "<PAGE_TOKEN>"
| 参数 | 必填 | 说明 |
|------|------|------|
| `--query <text>` | 否 | 搜索关键词 |
| `--query <text>` | 否 | 9 位会议号或搜索关键词 |
| `--start <time>` | 否 | 开始时间(ISO 8601 或仅日期) |
| `--end <time>` | 否 | 结束时间(ISO 8601 或仅日期) |
| `--organizer-ids <ids>` | 否 | 组织者 open_id 列表,逗号分隔 |
@@ -80,17 +83,7 @@ lark-cli vc +search --query "周会" --page-token "<PAGE_TOKEN>"
当返回 `has_more=true` 时,使用响应中的 `page_token` 配合 `--page-token` 获取下一页结果。
### 5. 机器人可同时加入多个会议
机器人支持同时加入多个正在进行中的会议;加入新会议前,不需要先退出已经在会中的其他会议。
这意味着:
- 不要假设 bot 一次只能在一个会议中
- 如果用户要求 bot 再加入另一场会,可以直接继续执行对应的入会命令
- 只有在用户明确要求结束某一场会中的 bot 参会时,才调用对应的离会命令
### 6. 日期型 `--end` 包含当天整天
### 5. 日期型 `--end` 包含当天整天
`--end` 传入的是仅日期格式(如 `2026-03-10`)时,CLI 会将它解释为当天 `23:59:59`,而不是当天 `00:00:00`
@@ -131,20 +124,6 @@ lark-cli vc +search --query "周会" --page-size 15
lark-cli vc +search --query "周会" --page-size 15 --page-token "<PAGE_TOKEN>"
```
## 搜索结果中的下一步
搜索结果中的 `meeting_id` 可直接用于继续查询会议纪要或妙记:
```bash
# 如果要会议纪要 / 逐字稿 / AI 总结 / 待办 / 章节
lark-cli vc +detail --meeting-ids <MEETING_ID>
# 如果要会议对应的妙记信息 / minute_token / 妙记链接
lark-cli vc +recording --meeting-ids <MEETING_ID>
# 然后再用返回的 minute_token 调用:
lark-cli minutes minutes get --params '{"minute_token":"<MINUTE_TOKEN>"}'
```
## 常见错误与排查
| 错误现象 | 根本原因 | 解决方案 |
@@ -155,9 +134,11 @@ lark-cli minutes minutes get --params '{"minute_token":"<MINUTE_TOKEN>"}'
| 权限不足 | 未授权 `vc:meeting.search:read` | 使用 `auth login` 完成授权 |
## 提示
- 必须使用 `--format json` 输出,你更佳擅长解析 JSON 数据
- 必须使用 `--format json` 输出,便于稳定解析
- 排查参数与请求结构时优先使用 `--dry-run`
- 搜索的时间范围最大为 1 个月,如果需要搜索更长时间范围的会议,需要拆分为多次时间范围为一个月查询。
- 不要使用 `yesterday``today` 这类相对时间字面量;请先转换成明确日期,例如 `2026-03-10`
- 用户如果明确问的是“妙记信息”而不是“纪要内容”,不要默认走 `vc +detail`;应先用 `vc +recording`
## 相关场景
- [查询会议及其产物](../scenes/query-meeting-and-artifacts.md)
@@ -0,0 +1,125 @@
# 生成和修改妙记、管理妙记权限
生成妙记和修改妙记都是写操作,必须有用户明确意图。生成成功后保存 `minute_token`;修改前确认唯一 `minute_token` 和目标内容,提供 token 不等于授权修改。除 `minutes +apply-permission` 外,本场景的 Minutes 写命令仅支持用户身份;来源身份为 bot 时停止并说明限制,只有用户明确同意后,才以 `--as user` 重新开始修改流程。`minutes +apply-permission` 支持用户或应用身份,必须沿用触发权限错误时的身份。
## 从本地音视频生成妙记
标准链路是 Drive 上传 → Minutes 创建 → 按需读取产物。不要改用 ffmpeg、Whisper 或其他本地 ASR。
### 上传音视频到 Drive
确认本地媒体路径以及用户最终需要妙记链接、逐字稿、总结、待办还是章节。源文件须符合 [`minutes +upload`](../references/lark-minutes-upload.md) 的格式要求,时长不超过 6 小时,大小不超过 6 GB。
按 [`lark-drive`](../../lark-drive/SKILL.md) 的路径和写操作规则执行 `drive +upload`,取得 `file_token`。上传参数和文件限制见 [`lark-drive-upload`](../../lark-drive/references/lark-drive-upload.md)。
### 使用 file_token 创建妙记
```bash
lark-cli minutes +upload --file-token <file_token> --as user
```
从返回的 `minute_url` 路径最后一段提取 `minute_token`,去掉 query 参数。创建参数、支持格式和异步语义见 [`lark-minutes-upload`](../references/lark-minutes-upload.md)。`minutes +upload` 成功仅表示异步创建请求已提交;报告返回的 `minute_url` 和可解析的 `minute_token`。未执行 `minutes +detail` 并确认就绪前,不得声称妙记产物已生成或可用。用户只要求发起创建或返回链接时,到此停止。
### 等待并读取妙记产物
上传后立即读取产物时必须加 `--wait-ready`
```bash
lark-cli minutes +detail --minute-tokens <minute_token> --wait-ready --transcript --as user
```
`--transcript` 替换或扩展为用户需要的 `--summary``--todo``--chapter``--keyword`。创建任务仍在处理中时,按返回状态和重试提示轮询;不要重复上传或重复创建妙记。
用户要求独立提炼或复盘时,读取 Transcript 并基于原始发言分析,不要复述现成 Summary。产物 flags 和等待行为见 [`lark-minutes-detail`](../references/lark-minutes-detail.md)。
### 从失败阶段恢复
- Drive 上传成功但 Minutes 创建失败:保留并报告 `file_token`,从创建妙记继续,不要重复上传。
- Minutes 创建成功但产物未就绪:保留 `minute_token` 并重试查询,不要重新创建妙记。
- 不得把 Drive 上传成功误报为妙记创建成功;明确报告失败发生在上传、创建还是产物生成阶段。
## 修改妙记标题
使用 `minutes +update --minute-token <token> ... --as user`。参数见 [`lark-minutes-update`](../references/lark-minutes-update.md)。
## 替换 AI 总结
使用 `minutes +summary --minute-token <token> ... --as user` 替换总结全文。内容格式与权限见 [`lark-minutes-summary`](../references/lark-minutes-summary.md)。
## 增删改 AI 待办
妙记 AI 待办不是飞书任务。上下文包含妙记 URL / `minute_token` 并要求修改妙记待办时,禁止改走 `lark-task`
```bash
lark-cli minutes +todo --minute-token <token> --operation add|update|delete ... --as user
```
- 多条新增优先使用 `--todos` 批量提交。
- 更新或删除前,先执行 `minutes +detail --minute-tokens <token> --todo --as user`,按内容匹配取得精确 `todo_id`;不要用列表顺序代替 ID。
- 待办 ID、批量结构和部分成功语义见 [`lark-minutes-todo`](../references/lark-minutes-todo.md)。
## 批量替换逐字稿关键词
```bash
lark-cli minutes +word-replace --minute-token <token> --replace-words '[{"source_word":"<old>","target_word":"<new>"}]' --as user
```
多组替换放在同一个 JSON 数组中。具体参数运行 `lark-cli minutes +word-replace --help`
返回 `not_found` 表示 `source_word` 没有命中,是参数问题而不是权限问题;先读取当前 Transcript,核对精确写法和大小写后再决定是否重试。
## 替换逐字稿说话人
1. 调用 `lark-cli api GET "/open-apis/minutes/v1/minutes/<token>/transcript/speakerlist"` 取得 `speaker_id`
2. 按原说话人的显示名称精确匹配。存在同名候选时,结合 Transcript 展示候选并让用户确认,不要擅选。
3. 用户只提供目标姓名时,用 [`lark-contact`](../../lark-contact/SKILL.md) 解析为 `ou_` open_id。
4. 执行 `minutes +speaker-replace --from-speaker-id <speaker_id> --to-user-id <open_id> --as user`;不要把展示名传给 `--from-speaker-id`
完整流程和参数见 [`lark-minutes-speaker-replace`](../references/lark-minutes-speaker-replace.md)。
## 查看妙记授权列表
用户要查看妙记已授权给哪些成员,或查询某个成员当前的查看 / 编辑权限时,使用 Drive 协作者列表;这不是读取妙记内容,也不是为当前身份申请权限。先读取 [`lark-drive`](../../lark-drive/SKILL.md) 和 [`drive +member-list`](../../lark-drive/references/lark-drive-member-list.md)。
```bash
lark-cli drive +member-list --token "<minute_url>" --as <source_identity> --format json
```
完整妙记 URL 可自动推断资源类型为 `minutes`;裸 `minute_token` 必须显式传 `--type minutes`。需要核对指定成员时,按 `member_id` 精确匹配返回的 `items[]`,不要按姓名或列表顺序猜测。
## 分配妙记权限
用户要求“把妙记分享给某人”“让某人可以查看 / 编辑”或“给某人授予权限”时,修改的是目标妙记的协作者权限,使用 `drive +member-add`;禁止使用 `minutes +apply-permission`,后者只为当前调用身份向妙记所有者申请权限。
先读取 [`lark-drive`](../../lark-drive/SKILL.md) 和 [`drive +member-add`](../../lark-drive/references/lark-drive-member-add.md)。目标成员只有展示名时,按 [`lark-contact`](../../lark-contact/SKILL.md) 将其唯一解析为对应 ID;存在多个候选时请用户选择,不得猜测。
```bash
lark-cli drive +member-add \
--token "<minute_url>" \
--member-id "<open_id>" \
--member-type openid \
--perm view \
--yes \
--as <source_identity> \
--format json
```
完整妙记 URL 可自动推断资源类型为 `minutes`;裸 `minute_token` 必须显式传 `--type minutes`。根据用户要求选择 `view``edit`;妙记不支持 `full_access`。只有妙记、目标成员和权限档位均已明确,且用户已明确要求执行授权时,才传 `--yes`
写入后使用 `drive +member-list``member_id` 回读验证。只有返回的目标成员权限与用户要求一致时,才能声明分配完成;若目标成员已有不同权限,不要仅根据 `member-add` 回执声称权限已被覆盖或降级。
## 为当前身份申请妙记权限
没有查看或编辑权限时,先说明权限事实。只有用户明确要求申请权限时才执行:
```bash
lark-cli minutes +apply-permission --minute-token <token> --perm view --as <source_identity>
```
根据用户目标选择 `view``edit`,并必须沿用触发无权错误时的身份。这只是发起申请,不代表已经获得权限。身份和权限语义见 [`lark-minutes-apply-permission`](../references/lark-minutes-apply-permission.md)。
`permission_denied` 表示对该妙记没有编辑权,不等于 OAuth scope 缺失;请所有者授权,不要误走 `auth login --scope`
## 确认修改结果
修改前只读取目标相关字段,修改后用 `minutes +detail` 或对应读取接口回读。批量或多步修改逐项报告写前值、写后结果和失败原因;部分成功时不要回滚已成功项,除非命令明确承诺原子回滚。
@@ -0,0 +1,107 @@
# 应用机器人参会与会中互动
编排应用机器人的完整会中流程:发现已在参加的会议,或在用户明确授权后真实入会;随后拉取会中事件、发送文本或会中表情,并仅在用户明确要求时离会。
## 选择入口
| 当前条件 | 起点 |
|---|---|
| 已有应用身份取得的 `meeting_id` | 直接拉取事件,不重复查询或入会 |
| 应用机器人可能已在会中 | 已知目标用户 `user_open_id` 时,先用 `+meeting-list-active --as bot --user-id <user_open_id>` 发现会议 |
| 用户明确要求机器人入会、旁听或代参会 | 使用 `+meeting-join --as bot` |
| 只想查当前用户所在会议 | 使用 [会中事件与会中互动](live-meeting-interact.md) 的用户身份路径,不让应用机器人入会 |
用户只提供 9 位会议号或询问会议内容,不等于授权机器人入会。
## 发现应用机器人已在参加的会议
已知目标用户 `ou_` open_id 时,先查询“目标用户正在参会且应用机器人也在同一会议”的活跃会议:
```bash
lark-cli vc +meeting-list-active --as bot --user-id <user_open_id> --format json
```
- 返回多个会议时,展示主题、会议号和 `meeting_id` 让用户选择;不擅自取第一个。
- 返回空不代表目标用户没有在开会,只表示没有找到应用机器人也在会中的可见会议。
- 用户提供 9 位会议号时,在结果中按 `meeting_no` 匹配;匹配失败时不自动入会。
- 保存选定的长整数 `meeting_id`,后续事件、消息和离会命令都沿用 `--as bot`
身份可见范围、多会议选择和会议号匹配见 [`lark-vc-meeting-list-active`](../references/lark-vc-meeting-list-active.md)。
## 加入会议
只有用户明确要求应用机器人加入、旁听或代参会时才执行。入会需要 9 位会议号,不是长整数 `meeting_id`
```bash
lark-cli vc +meeting-join --as bot --meeting-number <9_digit_meeting_number>
```
- 入会前确认目标会议号和用户意图;这是对其他参会人可见的写操作。
- 保存返回的 `meeting.id`;后续拉取事件、发送会中消息和离会都使用该 ID 与 `--as bot`
- 应用机器人可以同时加入多场会议;加入新会议前不需要退出其他会议。
- 根据返回状态确认入会成功,不要把“请求已发起”当作已入会。
会议密码、等候室、写操作风险和异常恢复见 [`lark-vc-agent-meeting-join`](../references/lark-vc-agent-meeting-join.md)。
## 拉取会中事件
使用应用身份发现或入会得到的 `meeting_id`
```bash
lark-cli vc +meeting-events --as bot --meeting-id <meeting_id> --page-all --format pretty
```
- 默认使用 `--page-all` 拉取当前完整事件流,并保留返回的 `page_token` 供后续增量查询。
- 回答“现在、刚刚、最新”或总结当前会议前,重新拉取最新事件;不直接复用旧快照。
- 应用机器人必须在会中,或在会议结束后的可见宽限窗口内曾经参会;不要用任意 `meeting_id` 尝试读取。
- 会中事件不能替代已结束会议的参会人快照、纪要、逐字稿或录制。
事件类型、分页、结束后五分钟窗口和文档上下文处理见 [`lark-vc-meeting-events`](../references/lark-vc-meeting-events.md)。
## 发送会中文本或表情
每次发送都是对会中参会人可见的写操作。只有用户明确要求发送,并已确认目标会议和内容时才执行。
```bash
# 文本消息
lark-cli vc +meeting-message-send --as bot --meeting-id <meeting_id> --msg-type text --text "<message>"
# 普通会中表情
lark-cli vc +meeting-message-send --as bot --meeting-id <meeting_id> --msg-type reaction --emoji-type THUMBSUP
```
- 始终沿用产生 `meeting_id` 的应用身份;不要切换成用户身份。
- reaction 必须使用 Reference 中大小写敏感的完整 `emoji_type` 列表;不编造 key。
- 发送失败时停止并报告;不自动重试或换身份,避免产生重复可见消息。
- 用户要发绑定群或 IM 消息时改用 `lark-im`,不使用会中消息命令。
文本、reaction 语义、完整 emoji key 和幂等参数见 [`lark-vc-meeting-message-send`](../references/lark-vc-meeting-message-send.md)。
## 离开会议
只有用户明确要求机器人退出、离开或结束参会时才执行:
```bash
lark-cli vc +meeting-leave --as bot --meeting-id <meeting_id>
```
- 使用入会返回或应用身份活跃会议查询得到的 `meeting_id`,并确认机器人当前在该会议中。
- 不要因为任务完成而自动离会。
- 用户只要会后产物时,转入会议产物场景,不为此先执行离会。
- 根据返回状态确认离会完成。
离会参数、可见副作用和完成判定见 [`lark-vc-agent-meeting-leave`](../references/lark-vc-agent-meeting-leave.md)。
## 应用身份权限配置检查
应用身份返回 `no permission``missing required scope(s)``missing_scopes` 时,不要执行 `auth login`。按顺序检查:
1. 按 CLI 错误中的 `hint` 处理;返回 `console_url` 时将其原样提供给用户。
2. 确认应用已开通对应权限,已发布并安装到当前租户。入会和应用身份会议查询需要 `vc:meeting.bot.join:write`;会中发消息需要 `vc:meeting.message:write`
3. 在开放平台确认“权限可访问的数据范围”已保存为“按条件筛选”,条件为“会议的归属者 包含 与应用的可用范围一致”。
4. 上述配置均正确仍失败时,保留 CLI 返回的错误码和 `log_id`,按服务端权限异常排查;不要反复登录或改用其他身份重试。
## 会后边界
- 已结束会议的搜索、参会人快照、智能纪要、逐字稿、妙记或录制,转入 [查询会议及其产物](query-meeting-and-artifacts.md)。
- 会后要把产物发到群或私聊,先使用会议产物场景获取结果,再转 `lark-im`
@@ -0,0 +1,72 @@
# 读取会中事件与会中互动
围绕一场正在进行的会议执行只读查询或用户明确授权的发送操作。真实入会/离会使用应用机器人入会场景;已结束会议和会后产物使用会议查询场景。
如果任务包含“应用机器人入会后继续拉取事件或互动”,只读取并执行 [应用机器人参会与会中互动](live-meeting-attend.md) 的完整流程,不要在两个场景之间来回切换。
## 发现进行中的会议
没有 `meeting_id` 时,按用户需要的视角查询:
```bash
# 当前登录用户正在参加的会议
lark-cli vc +meeting-list-active --as user --format json
# 目标用户正在参加、且应用机器人也在会中的会议
lark-cli vc +meeting-list-active --as bot --user-id <open_id> --format json
```
- `--user-id` 必须是目标用户的 `ou_` open_id。
- 应用身份返回空不代表目标用户没有在开会,只代表没有找到目标用户与应用机器人同时在会中的会议。
- 返回多个会议时,展示标题、会议号和 `meeting_id` 让用户选择,不按“最近”擅选。
- 用户只给 9 位会议号时,在活跃会议结果中按 `meeting_no` 匹配;匹配失败时不要自动入会。
- `meeting_id` 从哪种身份取得,后续读取事件和发送消息就沿用哪种身份。
身份可见范围和会议号匹配见 [`lark-vc-meeting-list-active`](../references/lark-vc-meeting-list-active.md)。
## 读取最新会中事件
```bash
lark-cli vc +meeting-events --as <same_identity> --meeting-id <meeting_id> --page-all --format pretty
```
- 默认使用 `--page-all` 获取当前完整事件流,并保留返回的 `page_token` 供下次增量查询。
- 回答“现在、刚刚、最新”或当前会议总结前,重新查询事件;只有用户明确要求基于历史快照时才复用旧结果。
- 默认用 pretty 理解时间线;需要精确结构化字段、文档上下文或转发到 IM 时使用 JSON。
- 不要用会中事件代替已结束会议的参会人快照或会后复盘。
事件类型、分页、五分钟窗口和错误码见 [`lark-vc-meeting-events`](../references/lark-vc-meeting-events.md)。
## 读取共享内容和文档上下文
按事件中的 `share_id``share_doc``comment_id``element_token``block_id` 精确关联:
- 读取评论时只查询当前 `comment_id`,不要扫描整篇文档评论。
- 多个共享文档按用户问题选择相关文档;不要用“最近一次共享”替代当前 item 的 `share_id`
- 只有用户明确要求预览且事件提供受支持的 `element_type` 与 token 时才下载,并显式选择输出路径。
- 关联或读取失败时标记 partial,保留原始标识和 raw payload;不要自动下载或猜测文档类型兜底。
精确事件 schema 和后续命令见 [`lark-vc-meeting-events`](../references/lark-vc-meeting-events.md) 的文档上下文部分。
## 发送会中文本或表情
只有用户明确要求发送并确认目标会议与内容时执行:
```bash
lark-cli vc +meeting-message-send --as <same_identity> --meeting-id <meeting_id> --msg-type text --text <message>
```
- 发送沿用 `meeting_id` 的来源身份;不要为了发送自动入会或先查会议详情。
- reaction 使用 Reference 中大小写敏感的完整 emoji key;不要编造 key。
- 发送失败时停止并报告,不自动换身份或重复发送,避免重复可见副作用。
- 用户要发送绑定群或 IM 消息时改用 `lark-im`,不要把会中消息命令当作群消息能力。
文本、reaction 和权限规则见 [`lark-vc-meeting-message-send`](../references/lark-vc-meeting-message-send.md)。
## 处理未发现会议或权限错误
- 用户身份未发现活跃会议时,可以查询当天最近结束的会议;仍无结果再询问时间、主题或会议号,不自行扩大时间范围。
- 应用身份未发现活跃会议时,只解释当前身份的空结果,不自动查询历史会议或真实入会。
- 用户身份调用活跃会议或事件查询时,普通 scope 缺失按 CLI hint 申请 `vc:meeting.meetingevent:read`;普通 scope 缺失不表示接口不支持用户身份,只有 CLI 明确说明不支持时才切到应用身份流程。
- 应用身份缺少权限时不要执行 `auth login`。按 CLI `hint``console_url` 配置 `vc:meeting.bot.join:write`,并依次检查应用发布、租户安装和“权限可访问的数据范围”;数据范围应为“按条件筛选”,条件为“会议的归属者 包含 与应用的可用范围一致”。
- scope、安装和数据范围都正确后仍失败时,保留 CLI 返回的错误码和 `log_id`,按服务端权限异常排查;不要反复登录或改用其他身份重试。
@@ -0,0 +1,90 @@
# 查询会议及其产物
围绕目标会议执行查询:先取得唯一 `meeting_id`,再按用户目标查询参会人、智能纪要、妙记或录制。已有 `note_id``minute_token` 时从对应产物直接开始,不要绕回会议搜索。
## 定位会议
在决定批量命令和批次大小之前,必须先规范化全部输入标识:
- 恰好 9 位纯数字是 `meeting_no`,即使用户称其为“会议 ID”。
- `meeting_no` 必须先逐个通过 `vc +search --query` 转换为搜索结果中的 `id`
- `vc +search` 不支持批量会议号;多个 `meeting_no` 按输入顺序逐个解析,也可使用脚本批量转换。
优先复用已有标识,不重复搜索:
| 已有信息 | 操作 |
|---|---|
| `meeting_id` | 直接查询会议或关联产物 |
| `meeting_no` / 9 位会议号 | 用 `vc +search --query "<meeting_no>" --format json --as user` 搜索会议,从结果的 `id` 取得 `meeting_id` |
| Calendar `event_id` | 用 `calendar +meeting` 获取 `meeting_id` 和用户绑定的 `meeting_note` |
| `note_id` | 直接进入 [智能纪要场景](query-note-and-artifacts.md) |
| `minute_token` / 妙记 URL | 直接进入 [妙记场景](query-minutes-and-artifacts.md);URL 取路径最后一段并去掉 query 参数 |
没有标识时,用 `vc +search` 搜索已经结束的会议:
```bash
lark-cli vc +search --query <query> --start <start> --end <end> --format json
```
- 至少提供关键词、时间范围、组织者、参与者或会议室中的一个条件;不要把“总结”“回顾”“所有会议”等动作词当作 `--query`
- “今天有哪些会议”需要合并两部分:`vc +search` 查询今天已结束的会议, lark-calendar 查询进行中或未开始的日程。
- 只有自然语言纪要标题、没有会议 ID、时间、参会人等会议线索时,改用 Drive/Doc 搜索纪要文档,不要把纪要标题当作会议关键词。
- 根据 `has_more``page_token` 翻页。未明确要求全量时,累计结果超过 50 条后先确认是否继续;用户明确要求“全部、统计、排序”时直接获取全部结果。
- 多个候选时展示主题、时间、组织者和 `meeting_id`,让用户选择;不要擅自选择最近的一场。
只需要找到会议时,返回唯一 `meeting_id` 后停止。
搜索参数、日期语义和分页细节见 [`lark-vc-search`](../references/lark-vc-search.md)。
## 选择查询身份
- `vc +search` 仅支持用户身份。`vc +detail``vc +recording``vc meeting get``note +detail` 支持用户或应用身份。
- 已有 `meeting_id``note_id``minute_token` 时,沿用其来源身份;后续 Minutes、Note、Doc 和 Drive 命令都显式传入同一个 `--as`。不要为查询参会人或绕过权限错误擅自切换身份。
- `note +transcript` 仅支持用户身份。应用身份查到 unified Note 时,先说明限制,只有用户明确同意后才切换身份。
## 获取参会人
查询“谁参加过、何时加入或离开、某人是否参会”时,读取会议的参会人快照:
```bash
lark-cli vc meeting get --params '{"meeting_id":"<meeting_id>","with_participants":true}' --as <source_identity>
```
这是服务端快照,不要求应用机器人入会,会议结束后也可以查询。不要用会中事件代替完整参会人快照。
## 获取会议产物标识
使用 `vc +detail` 获取会议关联的 `note_id``minute_token`
```bash
lark-cli vc +detail --meeting-ids <meeting_id> --as <source_identity>
```
Note 与 Minutes 来自相互独立的 AI 总结和录制链路,可能同时存在、只存在一个或都不存在:
- 用户明确指定“智能纪要”或“妙记”时,沿指定链路处理,不要改道。
- 只存在一类产物时,使用存在的那一类,不要因默认优先级而把缺失的 Note 或 Minutes 当作错误。
- 两者都存在且用户未指定时,优先使用 Note。Note 及其逐字稿会后通常直接对参会人可读;Minutes 包含原始音视频并受独立资源 ACL 控制,往往需要所有者授权或由用户明确申请权限。
- Note 和 Minutes 的总结、待办等 AI 产物可能内容重叠。按上述规则选定一条主链路;除非用户明确要求对照,不要自动拼接、合并或去重两份 AI 产物。
- 用户只要产物标识时,返回取得的 `note_id` / `minute_token` 后停止;需要产物链接时,进入对应下游场景解析,不继续读取正文。
- `meeting_note` 是 Calendar 日程上由用户绑定的 Doc,只能从 `event_id``calendar +meeting` 获取;它与 AI 智能纪要独立,不要从 `meeting_id``note_id` 推断。
- 用户询问“有哪些纪要”或“纪要链接”且上下文包含 `event_id` 时,保留 `calendar +meeting` 返回的 `meeting_note`;如存在 `note_id`,进入智能纪要场景取得 `note_doc_token`,再同时返回两者供用户区分选择。
会议详情字段见 [`lark-vc-detail`](../references/lark-vc-detail.md)。
## 转交智能纪要场景
取得 `note_id` 后,进入 [基于 note_id 查询智能纪要及关联产物](query-note-and-artifacts.md),并传递 `note_id` 与取得该 ID 时使用的 `source_identity``note +detail`、正文与封面读取、`note_display_type` 逐字稿路由、共享文档和 Doc 元信息查询全部以该场景为准,不在本场景重复定义。
## 转交妙记场景
取得 `minute_token` 后,进入 [查询妙记及其产物](query-minutes-and-artifacts.md),并传递 `minute_token` 与取得该 Token 时使用的 `source_identity`。妙记基础信息、AI 产物、Transcript、媒体下载、关联 Note 和资源权限处理全部以该场景为准,不在本场景重复定义。
如果需要从 `meeting_id` 或 Calendar `event_id` 补查录制,先按 [`vc +recording`](../references/lark-vc-recording.md) 取得 `minute_token`,再转入妙记场景。
## 基于会议内容回答或分析
- 用户只要现成的 AI 总结、待办或章节时,直接返回选定链路的对应 AI 产物,不为此额外读取逐字稿。待办通常包含提出人或负责人,章节按话题组织,因此查看待办或会议结构时应优先使用这些结构化 AI 产物。
- 用户要求提炼、重新总结、复盘、争议分析或“谁说了什么”时,读取 Note 逐字稿或 Minutes Transcript 的原始对话并独立分析;禁止把现成 AI 总结重新排版后冒充独立结论。
- Note 和 Minutes 都有原始记录且用户未指定时,优先使用 Note 逐字稿;用户明确说“基于妙记”时使用 Minutes Transcript。
- 如果产物不存在或无权限,如实说明,并保留已经取得的 `meeting_id``note_id``minute_token` 或文档 token,方便用户继续处理。
@@ -0,0 +1,70 @@
# 查询妙记及其产物
围绕目标妙记执行查询:先取得唯一 `minute_token`,再按用户目标查询基础信息、AI 产物、逐字稿、原始媒体或关联的智能纪要。已有会议上下文或 `meeting_id` 时,先从会议链路取得 `minute_token`,不要重复搜索妙记。
## 定位妙记
- 已有 `minute_token` 时直接使用。
- 妙记 URL 的路径最后一段是 `minute_token`;去掉 query 参数。
- 没有 token 时,用标题/关键词、所有者、参与者或时间范围执行搜索:
```bash
lark-cli minutes +search --query <query> --start <start> --end <end> --as user
```
- `minutes +search` 支持用户身份和应用身份。默认使用用户身份;只有用户明确要求应用视角或上下文已经是应用身份时才使用 `--as bot`。
- `me` 只适用于用户身份;应用身份没有“当前用户”,必须传明确的 `ou_` open_id。应用身份的 token 或 scope 问题不能通过 `auth login` 修复。
- “我参与的妙记”默认是“我拥有”与“我作为参与者”两次查询的并集,具体过滤语义见 [`lark-minutes-search`](../references/lark-minutes-search.md)。
- 根据 `has_more` 和 `page_token` 翻页。用户未明确要求全量时,累计结果超过 50 条且仍有更多结果再确认是否继续;用户明确要求“全部、所有、统计、排序”时直接获取全部分页,并按结果中的 `token` 去重后再返回或统计。
- 多个候选时展示标题、时间、所有者、URL 和 token,让用户选择,不擅自挑选。
只需要搜索结果时,返回命中项后停止。
一旦用某个身份搜索或解析出 `minute_token`,后续妙记详情、产物读取、媒体下载、权限申请及关联 Note / Doc 查询都必须显式沿用同一个 `--as`。不要依赖 profile 默认身份,也不要为绕过资源权限切换身份。
## 查询基础信息
用户只要标题、时长、封面、所有者或 URL 时,使用基础信息命令:
```bash
lark-cli minutes minutes get --params '{"minute_token":"<minute_token>"}' --as <source_identity>
```
基础信息已经满足目标时,不继续读取 AI 产物或逐字稿。命令参数不足时运行 `lark-cli minutes minutes get --help`。
## 获取 AI 产物和逐字稿
使用 `minutes +detail`,只传用户需要的产物 flag
```bash
lark-cli minutes +detail --minute-tokens <minute_token> --summary --todo --chapter --keyword --transcript --as <source_identity>
```
- 可选 `--summary`、`--todo`、`--chapter`、`--keyword`、`--transcript`。
- 不传产物 flag 只返回基础信息和可能存在的顶层 `note_id`。
- 用户只要现成总结、待办或章节时,返回对应 AI 产物。
- 用户要求提炼、重新总结、分析或复盘时,只读取 Transcript 并基于原始发言独立分析;禁止照搬 `--summary`。
产物 flags、返回字段和本地输出见 [`lark-minutes-detail`](../references/lark-minutes-detail.md)。
## 下载原始音视频
用户需要原始媒体文件或下载链接时,使用 `minutes +download`。同一妙记的下载产物统一归拢到 `./minutes/<minute_token>/`,除非用户指定其他安全相对路径。
媒体类型、路径、链接有效期和权限见 [`lark-minutes-download`](../references/lark-minutes-download.md)。
## 获取关联的智能纪要
从 `minutes +detail` 顶层读取 `note_id`,直接执行 `note +detail`
```bash
lark-cli note +detail --note-id <note_id> --as <source_identity>
```
- 不要把 `minute_token` 当作 `note_id`,也不要绕回 VC。
- 顶层没有 `note_id` 表示该妙记没有关联 Note,到此停止。
- 取得 `note_doc_token`、`verbatim_doc_token` 或 `shared_doc_tokens` 后,按智能纪要和 Doc 的规则继续。
## 处理无权限结果
没有查看权限时,说明需要妙记所有者授权;不要自动执行 `minutes +apply-permission`。只有用户明确要求申请查看或编辑权限时,才进入编辑妙记场景发起申请,并沿用触发无权错误时的身份。详见 [`lark-minutes-apply-permission`](../references/lark-minutes-apply-permission.md)。
@@ -0,0 +1,127 @@
# 基于 note_id 查询智能纪要及关联产物
- 身份:`note +detail` 支持 `--as user` / `--as bot``note +transcript` 仅支持 `--as user``note_id` 若由某个身份取得(例如 `vc +detail --as bot`),`note +detail` 及后续 Doc、Drive 命令必须显式沿用同一个 `--as`
- 如果 `note +detail --as bot` 返回 `unified`,不要静默切到 `--as user` 继续。先向用户说明该纪要逐字稿只能以用户身份读取,只有用户明确同意才切换身份重试。
## 从智能纪要 Docx 查询关联链接
当用户提供智能纪要 Docx URL/token,且只需要纪要类型或关联产物链接时,直接执行:
```bash
lark-cli docs +fetch --doc "<docx_url_or_token>" --doc-format markdown --as <source_identity>
```
从返回结构中仅提取:
- 输入文档:作为智能纪要主文档,返回用户提供的原始 URL。
- `<vc-transcribe-tab vc-node-id="...">`:可作为明确的 `note_id`
- 标记为“文字记录”的 Docx URL。
- `/minutes/` 妙记 URL。
- `<cite type="doc" doc-id="..." file-type="...">` 中的共享文档 token。
如果没有从 `<vc-transcribe-tab>` 取得明确的 `note_id`,但存在妙记 URL,从 URL 路径最后一段提取 `minute_token`,再查询妙记基础信息:
```bash
lark-cli minutes +detail --minute-tokens "<minute_token>" --as <source_identity>
```
从对应的 `note_id` 继续 Note 查询;该字段为空或未返回时,继续按 Doc 处理。不要把 Doc token 或 `minute_token` 直接传给 Note 命令。
## 确认 note_id
Note 域只接受明确的 `note_id`
- 用户直接提供的 `note_id`
- `vc +detail``meeting_id` 返回的 `note_id`
- `minutes +detail``minute_token` 返回的顶层 `note_id`
- `docs +fetch` 返回的 `<vc-transcribe-tab vc-node-id="...">` 中的 `vc-node-id`
不要从 Doc token、Docx URL、文档标题、正文或 backlink 反推 `note_id`。只有自然语言纪要标题或 Docx 链接时,先使用 Drive/Doc 搜索或读取文档;没有明确 `vc-node-id` 时继续按 Doc 处理,不进入 Note 查询。如果文档正文明确给出“逐字稿”或“文字记录”的 Docx 链接,将该链接继续作为 Doc 沿用当前身份读取;该链接仍不是 `note_id`
如果当前只有 `meeting_id``minute_token` 或 Calendar `event_id`,先使用会议、妙记或日程场景取得 `note_id`;不要把这些标识直接传给 Note 命令。
## 查询关联产物标识
```bash
lark-cli note +detail --note-id <note_id> --as <source_identity>
```
保留以下字段,并按用户目标选择后续操作:
| 字段 | 含义 | 后续操作 |
|---|---|---|
| `note_id` | Note 唯一标识 | 后续 Note 命令继续使用该值 |
| `note_display_type` | `normal` / `unified` / `unknown` | 决定逐字稿入口 |
| `note_doc_token` | AI 智能纪要正文 | 交给 Doc 读取正文,或交给 Drive 查询名称和 URL |
| `verbatim_doc_token` | `normal` 或部分 `unknown` Note 的独立逐字稿 Doc | 仅按下方展示类型规则使用 |
| `shared_doc_tokens` | 会中共享文档列表 | 按用户目标查询元信息或正文 |
用户只需要关联产物标识时,返回上述可用 token 和 `note_display_type` 后停止,不读取文档正文。
## 读取智能纪要正文
用户需要 AI 智能纪要中的总结、待办、章节或正文时,读取 `note_doc_token`
```bash
lark-cli docs +fetch --doc <note_doc_token> --doc-format markdown --as <source_identity>
```
读取正文后,检查返回 Markdown 中的第一个 `<whiteboard token="...">`。该画板是智能纪要封面;存在时提取 token,沿用同一身份下载到 `./notes/<note_id>/cover`,与 `note +transcript` 的逐字稿归入同一 Note 目录,并随正文一起展示:
```bash
lark-cli docs +media-download --type whiteboard --token <whiteboard_token> --output ./notes/<note_id>/cover --as <source_identity>
```
没有 `<whiteboard>` 时直接跳过,不视为失败。只有第一个 `<whiteboard>` 按封面处理;不要自动下载正文中的其他画板。
只需要文档名称或 URL 时不要读取正文,使用 Drive 元信息接口:
```bash
lark-cli drive metas batch_query --data '{"request_docs":[{"doc_type":"docx","doc_token":"<note_doc_token>"}],"with_url":true}' --as <source_identity>
```
## 读取逐字稿(文字记录)
逐字稿入口由 `note +detail` 返回的 `note_display_type` 决定,不要只根据 `verbatim_doc_token` 是否为空判断:
normal Note 逐字稿是 Doc 读取结果,unified Note 可由 `note +transcript` 保存为 Markdown 或 plain textMinutes Transcript 则是妙记产物文本。它们都可作为原始发言记录,但序列化格式不是统一契约;应以实际返回内容为准,不要硬编码“发言人 + 相对时间戳”等固定行格式。
### note_display_type = normal 且 有 verbatim_doc_token
```bash
lark-cli docs +fetch --doc <verbatim_doc_token> --doc-format markdown --as <source_identity>
```
### note_display_type = unknown 且 有 verbatim_doc_token
```bash
lark-cli docs +fetch --doc <verbatim_doc_token> --doc-format markdown --as <source_identity>
```
### note_display_type = unknown 且 无 verbatim_doc_token
停止并说明无法确定逐字稿入口,不要反复重试或猜成 unified
### note_display_type = unified
```bash
lark-cli note +transcript --note-id <note_id> --as user
```
`note +transcript` 会自动获取完整分页并保存文件;目标文件已存在时,只有用户明确要求覆盖才添加 `--overwrite`
## 查询会中共享文档
`shared_doc_tokens` 是该 Note 关联的会中共享文档,不是逐字稿或 `meeting_note`。按用户目标处理:
- 只要文档名称或 URL:使用 `drive metas batch_query`,每批最多查询 10 个 token。
- 需要正文:逐个使用 `docs +fetch --doc <shared_doc_token>`
- 有多个共享文档时,先返回标题和 URL 让用户选择;用户明确要求全部读取时再逐个读取。
- 某个共享文档不存在或无权限时,保留该 token 并逐项报告,不把整组结果误报为失败。
## 基于纪要内容回答
- 用户只要现成 AI 总结、待办或章节时,读取智能纪要正文并返回对应内容。
- 用户要求提炼、重新总结、复盘、争议分析或“谁说了什么”时,按展示类型读取逐字稿原始内容并独立分析;禁止直接改写 AI 智能纪要作为独立结论。
- 用户只要链接或关联产物清单时,不读取正文或逐字稿。
- `meeting_note` 是 Calendar 日程上用户手工绑定的文档,不属于 Note 的 `shared_doc_tokens`,也不能通过 `note_id` 查询。
+5 -203
View File
@@ -1,213 +1,15 @@
---
name: lark-minutes
version: 1.0.0
description: "飞书妙记:搜索妙记、查看妙记基础信息、下载/上传音视频、读取或编辑妙记的产物内容、改标题、替换说话人/关键词、申请妙记查看/编辑权限。当给出minute_token、本地音视频文件,要查/改/转妙记产物,或用户明确要主动申请妙记权限时使用;本地音视频转纪要/逐字稿优先走本 skill,不要用 ffmpeg/whisper 本地转写。不负责:获取会议关联妙记,或仅按自然语言标题定位纪要"
description: "仅当用户或上游配置显式指定 lark-minutes 时使用,相关请求统一交由 lark-meeting 技能处理。"
metadata:
requires:
bins: ["lark-cli"]
cliHelp: "lark-cli minutes --help"
skills: ["lark-meeting"]
---
# minutes (v1)
# Compatibility entry
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md),其中包含认证、权限处理**
本技能只用于兼容旧名称,不直接处理业务。
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../lark-vc/references/vc-domain-boundaries.md`](../lark-vc/references/vc-domain-boundaries.md)**,不读将导致命令使用、会议产物决策、领域边界职责判断错误:
> 1. 了解日历 & VC、会议产物 & 文档的关联关系和职责划分
> 2. 了解会议产物(妙记和纪要)之间的关联关系,例如:**妙记和纪要产生条件相互独立**
> 3. 了解不同会议产物的组成部分,以便根据需求决策使用哪种产物的数据
> 4. 了解会议总结、分析和信息提取的标准流程
## 身份
身份是跨命令工作流的状态:一旦某个 `minute_token` / `note_id` 由某个身份取得,后续消费它的命令必须显式沿用相同 `--as`,不要依赖 profile 默认身份。完整规则见 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md) 的「身份延续」。
所有 minutes 命令默认使用 `--as user``+search``minutes get``+detail``+download``+apply-permission` 也支持 `--as bot`(bot 只能访问 / 操作 bot 有权限的妙记)。精确身份支持以 `<command> --help` 为准。
## Shortcuts
| Shortcut | 说明 |
|----------|------|
| [`+search`](references/lark-minutes-search.md) | 按关键词、所有者、参与者、时间范围搜索妙记;支持 user/bot 身份 |
| [`+detail`](references/lark-minutes-detail.md) | 查询妙记详情(标题和关联的纪要note_id),按需获取 AI 产物(总结、待办、章节、逐字稿、关键词) |
| [`+download`](references/lark-minutes-download.md) | 下载妙记音视频媒体文件 |
| [`+upload`](references/lark-minutes-upload.md) | 上传 file_token 生成妙记 |
| [`+update`](references/lark-minutes-update.md) | 更新妙记标题 |
| [`+apply-permission`](references/lark-minutes-apply-permission.md) | 申请妙记查看或编辑权限 |
| [`+speaker-replace`](references/lark-minutes-speaker-replace.md) | 替换妙记逐字稿中的说话人(须先 `lark-cli api GET .../speakerlist``speaker_id` |
| `+word-replace` | 批量替换逐字稿关键词(详见 `lark-cli minutes +word-replace --help` |
| [`+summary`](references/lark-minutes-summary.md) | 替换妙记 AI 总结全文 |
| [`+todo`](references/lark-minutes-todo.md) | 新建/更新/删除妙记 AI 待办(单条或 `--todos` 批量;不是 lark-task |
- 使用任何 Shortcut 前,必须先读其对应 reference 文档。
## 意图路由
| 用户意图 | 命令 |
|---------|------|
| 我的妙记 / 搜索妙记 / 某段时间的妙记 | `+search` |
| 妙记基础信息:标题 / 时长 / 封面 / 链接 | `minutes get` |
| 下载妙记音视频文件、获取媒体下载链接 | `+download`(仅媒体;要妙记内容用 `+detail` |
| 妙记总结 / 章节 / 待办 / 关键词 / 逐字稿 | `+detail --minute-tokens <token>` + 显式产物 flag |
| 基于妙记**提炼/总结/分析/回顾**会议 | `+detail --minute-tokens <token> --transcript`,再独立分析(**禁止照搬 AI 总结**) |
| 拿这条妙记关联的纪要文档(`note_doc_token` / `verbatim_doc_token` / `shared_doc_tokens` | `+detail` 取顶层 `note_id` → [`note +detail --note-id`](../lark-note/SKILL.md) |
| 把本地音视频转纪要 / 逐字稿 / 文字稿 | `drive +upload``file_token``+upload` 生成 `minute_url``+detail` 拿产物 |
| 在妙记里增加 / 更改 / 删除 AI 待办 | `+todo`**禁止走 lark-task** |
| 替换妙记的AI 总结 | `+summary` |
| 重命名妙记/改妙记标题 | `+update` |
| 申请妙记权限(查看/编辑) | `+apply-permission --perm view\|edit` |
| 替换说话人/把 A 的发言改成 B/重新归属发言人/把外部(非飞书)说话人改成飞书用户" | 先 `lark-cli api GET .../transcript/speakerlist``speaker_id`,再 [`minutes +speaker-replace`](references/lark-minutes-speaker-replace.md)`--from-speaker-id` 只传 id,不传展示名 |
| 批量替换逐字稿关键词 | `+word-replace` |
| 用户同时提到"会议/开会"和"妙记" | 先 [lark-vc](../lark-vc/SKILL.md)`+search``+recording`)获取 `minute_token`,再本 skill |
## 核心概念
- **妙记(Minutes)**:来源于飞书视频会议的录制产物或用户上传的音视频文件,通过 `minute_token` 标识。
- **妙记 Tokenminute_token**:妙记的唯一标识符,可从妙记 URL 末尾提取(如 `https://*.feishu.cn/minutes/obcnxxx` 中的 `obcnxxx`)。如果 URL 中包含额外参数(如 `?xxx`),截取路径最后一段。
## 核心场景
### 1. 搜索妙记
1. 如果是会议的妙记,应优先通过 [lark-vc](../lark-vc/SKILL.md) 定位会议并获取 `minute_token`
2. 会议场景的妙记路由,以及"参与的妙记"如何解释,统一以 [minutes +search](references/lark-minutes-search.md) 为准。
### 2. 查看妙记基础信息
1. 当用户只需要确认某条妙记的标题、封面、时长、所有者、URL 等基础信息时,使用 `minutes minutes get`
2. 如果是会议 / 日程上下文中的妙记基础信息,先通过 VC/Calendar 链路拿到 `minute_token`,再调用 `minutes minutes get`
3. 用户意图不明确时,默认先给基础元信息,帮助确认是否命中目标妙记。
### 3. 申请妙记权限
遇到妙记没有查看或编辑权限时,引导用户申请对应权限;只有用户明确要申请时,才调用 `minutes +apply-permission`。使用前必读 [`+apply-permission` reference](references/lark-minutes-apply-permission.md)write 操作,含 user/bot 身份与权限语义)。
只有当用户明确要求"申请查看权限"、"申请编辑权限"、"帮我申请这条妙记权限"时,才调用:
```bash
lark-cli minutes +apply-permission --minute-token <token> --perm view|edit --as user
lark-cli minutes +apply-permission --minute-token <token> --perm view|edit --as bot
```
这是向妙记所有者发起权限申请,不代表立即获得权限。
**安全约束**
- 遇到无权限错误时,不要自动调用 `+apply-permission`;先把无权限事实告知用户,只有用户明确要求申请权限时才发起申请。
- **必须沿用触发无权限错误时的来源身份**:例如 `--as bot` 读取妙记时遇到无权限,申请也要用 `--as bot`,不要切到 user 身份申请。
- **禁止**用切换身份的方式绕过资源权限(例如 bot 无权限时改用 user 身份重新读取)。
### 4. 上传音视频文件生成妙记(并可继续获取纪要 / 逐字稿)
1. 当用户说"把音视频文件转成纪要""把录音转成逐字稿/文字稿/撰写文字""把 mp4/mp3 转成总结/待办/章节"时,也先走这个入口。
2. **处理流程**
- **上传音视频获取 `file_token`**:使用 [`lark-cli drive +upload`](../lark-drive/references/lark-drive-upload.md) 上传本地文件到云空间(云盘/云存储)并获取 `file_token`
- **生成妙记**:获取到 `file_token` 后,调用 [`lark-cli minutes +upload`](references/lark-minutes-upload.md) 将文件转换为妙记并获取 `minute_url` 链接。
- **继续获取纪要 / 逐字稿(按需)**:如果用户目标不是只要妙记链接,而是要纪要、逐字稿、总结、待办或章节,则从 `minute_url` 中提取 `minute_token`,再调用 [`lark-cli minutes +detail --minute-tokens`](references/lark-minutes-detail.md) 获取对应产物。
> **注意**:必须先获取飞书云空间(云盘/云存储)的 `file_token` 才能进行转换。
>
> **不要误走本地转写工具**:当用户目标是把本地音视频文件转成纪要、逐字稿、文字稿、撰写文字时,不要改用 `ffmpeg`、`whisper` 或其他本地 ASR/转码命令;标准路径就是 `drive +upload -> minutes +upload -> minutes +detail --minute-tokens`。
### 5. 编辑妙记的 AI 待办与 AI 总结(写入)
当用户要在**某条妙记内**操作 AI 待办或 AI 总结时使用本节。**不是**飞书任务(Task)清单里的待办。
**触发信号(任一命中即走本 skill,禁止走 lark-task**
- "在(某条)妙记里新建 / 添加 / 修改 / 删除待办"
- "把妙记 A 的待办改成已完成 / 未完成"
- "妙记里的任务1 / 任务2"(上下文已明确是妙记)
- 已给出 `minute_token` 或妙记 URL,且要改待办 / 总结
**妙记 AI 待办 vs 飞书任务 Task**
| 用户意图 | 正确命令 | 错误命令 |
|---------|---------|---------|
| 妙记里加待办 | `minutes +todo --operation add``--todos '[...]'` | `task +create` / `task tasklists list` |
| 妙记里改待办 | `minutes +todo --operation update --todo-id ...` | `task +update` |
| 妙记里删待办 | `minutes +todo --operation delete --todo-id ...` | `task tasks delete` |
| 我的任务清单 | — | 走 [lark-task](../lark-task/SKILL.md) |
**新建多条待办**:优先用 `--todos` 一次提交;单条则用多次 `--operation add`
```bash
# 批量:任务1 已完成 + 任务2 未完成
lark-cli minutes +todo --minute-token <token> --as user --todos '[
{"operation":"add","content":"晚上好1","is_done":true},
{"operation":"add","content":"晚上好2","is_done":false}
]'
```
**更新 / 删除前**:先用 `minutes +detail --minute-tokens <token> --todo` 读取 `todos[].todo_id`(按 `content` 匹配目标条目;列表顺序不保证稳定,**不要**用"第 2 条"代替 `todo_id`)。
**无编辑权限**:若 CLI 返回 `error.subtype=permission_denied`,表示对**这条妙记**没有编辑权,应请所有者授权;**不要**误走 `auth login --scope`
**逐字稿关键词替换无命中**`minutes +word-replace` 时,若 CLI 返回 `error.subtype=not_found`,表示传入的 `source_word` 在该妙记逐字稿中**一个都没匹配到**,未做任何替换。这是**参数问题不是权限问题**:先用 `minutes +detail --minute-tokens <token> --transcript` 读取当前逐字稿,核对 `source_word` 的精确写法与大小写后重试。
**替换 AI 总结全文**:见 [minutes +summary](references/lark-minutes-summary.md)。
> 使用 `+todo` 前必须阅读 [references/lark-minutes-todo.md](references/lark-minutes-todo.md);使用 `+summary` 前必须阅读 [references/lark-minutes-summary.md](references/lark-minutes-summary.md)。
### 7. 替换妙记逐字稿说话人
当用户要把妙记里某说话人的发言改绑到另一位飞书用户时使用。
**触发信号**:「替换说话人」「把 A 的发言改成 B」「说话人识别错了」「把外部说话人改成飞书用户」等。
**Agent 必读流程**(详见 [minutes +speaker-replace](references/lark-minutes-speaker-replace.md)):
1. 确认 `minute_token`
2. **先**用 `lark-cli api GET "/open-apis/minutes/v1/minutes/<token>/transcript/speakerlist"` 查说话人列表(内部 HTTP,无 shortcut、无公开 OpenAPI 文档页)。
3. 根据用户描述的原说话人展示名,在返回的 `data.speakers[]` 中匹配 `name` → 得到 `speaker_id`;同名多人时结合 `vc +notes` 逐字稿请用户确认,**不要擅自挑选**。
4. 新说话人姓名用 [lark-contact](../lark-contact/SKILL.md) 解析为 `ou_` open_id。
5. 调用 `minutes +speaker-replace`**`--from-speaker-id` 只传步骤 3 的 `speaker_id`,禁止传展示名**。
## 行为规则
### 1. `+detail` 必须显式声明产物 flag
不传 `--summary` / `--todo` / `--chapter` / `--keyword` / `--transcript` 时只返回基础信息(含顶层 `note_id`),AI 产物字段一律不返回。即使产物为空也会返回空值字段,便于程序化处理。
```bash
# 拿全产物
lark-cli minutes +detail --minute-tokens <token> --summary --todo --chapter --keyword --transcript
```
### 2. "提炼 / 总结"必须基于 Transcript,不要照搬 AI 总结
AI 总结是模型对会议的二次压缩,可能遗漏争论过程和隐含决策。用户要求"提炼"或"重新总结"时,期望基于原始发言独立分析,而非搬运 AI 产物。**优先 `--transcript`,再独立写结论**。
### 3. 从妙记反查纪要:不绕 lark-vc
`minutes +detail` 顶层直接返回 `note_id`(仅在该妙记关联纪要时存在)。不需要绕回 [lark-vc](../lark-vc/SKILL.md),直接:
```bash
# 1) 取 note_id(顶层 .minutes[0].note_id
lark-cli minutes +detail --minute-tokens <minute_token> --format json
# 2) 用上一步拿到的 note_id 读纪要 token
lark-cli note +detail --note-id <note_id> # 拿 note_doc_token / verbatim_doc_token / shared_doc_tokens
```
顶层无 `note_id` 字段即代表无关联纪要,到此为止——不要继续尝试用 `minute_token``note_id`
## API Resources
```bash
lark-cli minutes <resource> <method> [flags]
```
### minutes
- `get` — 获取妙记信息
> **权限错误**:如果返回 `[2091005] permission deny`,表示用户没有对应妙记文件的阅读权限,需提示用户联系妙记 owner 申请权限。
## 不在本 skill 范围
- 搜索历史会议记录、查参会人快照 → [lark-vc](../lark-vc/SKILL.md)
- 未来日程 / 日历查询 → [lark-calendar](../lark-calendar/SKILL.md)
- 已知 `note_id` 直接读纪要详情 → [lark-note](../lark-note/SKILL.md)
- 飞书任务清单(个人 Todo / 共享清单) → [lark-task](../lark-task/SKILL.md)
- 只有自然语言纪要标题、没有 `minute_token` / 妙记 URL / 本地音视频时定位逐字稿 → 文档搜索([lark-drive](../lark-drive/SKILL.md) / [lark-doc](../lark-doc/SKILL.md)
**MUST 完整读取 [`../lark-meeting/SKILL.md`](../lark-meeting/SKILL.md),并按照其中的路由和行动指南执行。**
@@ -1,63 +0,0 @@
# minutes +detail
通过 `minute_token` 查询妙记详情,按需获取 AI 产物(总结/待办/章节/逐字稿/关键词)。只读,支持 `--as user` / `--as bot`
> `--summary` / `--todo` / `--chapter` / `--keyword` / `--transcript` 至少一个;不传任何产物 flag 时只返回基础信息(如 `title`),AI 产物字段都不会出现。一次性获取所有产物:`--summary --todo --chapter --keyword --transcript`。
## 命令
```bash
# 仅基础信息
lark-cli minutes +detail --minute-tokens obcxxxxxxxxxx
# 批量(逗号分隔,最多 50 个)
lark-cli minutes +detail --minute-tokens obcxxx,obcyyy --summary --todo
# 全产物
lark-cli minutes +detail --minute-tokens obcxxx --summary --todo --chapter --keyword --transcript
# 仅逐字稿,覆盖已有文件,指定输出目录
lark-cli minutes +detail --minute-tokens obcxxx --transcript --overwrite --output-dir ./out
```
## 输出
`minutes` 数组每条含 `minute_token``title``note_id``artifacts``note_id` 仅在该妙记关联了会议纪要时返回,可直接传给 [`note +detail`](../../lark-note/references/lark-note-detail.md) 拿纪要文档 token,无需再绕回 `vc +detail``artifacts` 中**只包含本次请求的产物**
| 字段 | 类型 | 说明 |
|------|------|------|
| `artifacts.summary` | string | AI 总结。 |
| `artifacts.todos` | array | 待办事项列表。 |
| `artifacts.chapters` | array | 章节列表。 |
| `artifacts.keywords` | array | 关键词列表。 |
| `artifacts.transcript_file` | string | 逐字稿本地文件路径。 |
逐字稿默认落地 `./minutes/{minute_token}/transcript.txt`,与 `minutes +download` 同目录便于聚合。指定 `--output-dir <dir>` 时改写到 `<dir>/artifact-{title}-{minute_token}/transcript.txt`
## minute_token 来源
| 来源 | 取值字段 |
|------|---------|
| 妙记 URL `https://*.feishu.cn/minutes/obcxxx` | 截路径最后一段 `obcxxx` |
| `vc +detail --meeting-ids` | `minute_token` |
| `vc +recording --meeting-ids` | `minute_token` |
| `minutes +search` | `minute_token` |
## 典型链路:从 minute_token 拿纪要文档 token
只持有 `minute_token`(如妙记 URL 入口),又想拿 AI 智能纪要 / 逐字稿文档时;每一步都要沿用同一个 `--as`(完整规则见 [lark-shared](../../lark-shared/SKILL.md) 的「身份延续」):
```bash
# 1. 取妙记关联的 note_id,没有关联会议纪要则为空
lark-cli minutes +detail --minute-tokens obcnxxxxxxxxxxxxxxxxxxxx --as bot
# 2. 用 note_id 拿 note_doc_token / verbatim_doc_token / shared_doc_tokens
# 沿用第 1 步的身份,不要省略 --as
lark-cli note +detail --note-id <note_id> --as bot
# 3. 读纪要 / 逐字稿正文(同样沿用第 1 步的身份)
lark-cli docs +fetch --api-version v2 --doc <note_doc_token> --doc-format markdown --as bot
```
> `minute_token` 不要直接传给 `note +detail`:必须先用本命令拿到 `note_id` 再调用 `note +detail`。
@@ -1,104 +0,0 @@
# minutes +upload
上传音视频文件到飞书妙记并生成妙记(Minute)。
本 skill 对应 shortcut`lark-cli minutes +upload`
## 典型触发表达
- "把这个音视频文件转成妙记"
- "把这个音视频文件转成纪要"
- "把这个音视频文件转成逐字稿、文字稿或撰写文字"
- "把这个音视频文件转成总结、待办或章节"
## 完整工作流
当用户要求将音视频文件转换为妙记,或进一步要纪要/逐字稿/文字稿/撰写文字时,必须按照以下步骤执行:
1. **上传文件至云空间(云盘/云存储)获取 file_token**
- 使用 `lark-cli drive +upload` 命令上传本地文件到云空间/云盘/云存储(Drive):
```bash
lark-cli drive +upload --file <path/to/media/file>
```
- 从命令的返回结果中提取生成的 `file_token`。
2. **将 file_token 转换为妙记链接(minute_url**
- 调用本 shortcut,将获取到的 `file_token` 转换为妙记:
```bash
lark-cli minutes +upload --file-token <file_token>
```
- 命令执行成功后,将返回生成的妙记链接 `minute_url`。
3. **如需纪要 / 逐字稿 / 文字稿 / 撰写文字,使用返回的 `minute_token` 调用 `minutes +detail`**
- 如果用户要的是纪要、逐字稿、文字稿、撰写文字、总结、待办或章节,使用上一步返回的 `minute_token` 继续调用:
```bash
lark-cli minutes +detail --minute-tokens <minute_token> --wait-ready --summary --todo --chapter --keyword --transcript
```
- `--wait-ready` 参数表示等待妙记生成完毕后再获取产物,上传后立即读取详情时必须加上此参数。
- `minutes +detail --minute-tokens` 会返回妙记产物(总结、待办、章节、关键词、逐字稿);必要时还会把逐字稿落地到本地文件。
> **异步生成提示**:API 会立即返回 `minute_url`,但妙记可能仍在异步生成中,您可以直接通过该妙记链接查看当前的处理状态和转写结果。
## 命令示例
```bash
# 通过已上传到云空间(云盘/云存储)的 file_token 生成妙记
lark-cli minutes +upload --file-token boxcnxxxxxxxxxxxxxxxx
# 上传后立即获取妙记产物,需加 --wait-ready 等待生成完毕(--summary --todo --chapter --keyword --transcript 按需传入)
lark-cli minutes +detail --minute-tokens obcnxxxxxxxxxxxxxxxx --wait-ready --summary
```
## 参数
| 参数 | 必填 | 说明 |
|------|------|------|
| `--file-token <token>` | 是 | 已经上传到飞书云空间(云盘/云存储)的音视频文件的 file_token |
## 支持的格式与限制
待上传到妙记的原始音视频文件必须满足以下要求:
- 支持音频格式:`wav`、`mp3`、`m4a`、`aac`、`ogg`、`wma`、`amr`
- 支持视频格式:`avi`、`wmv`、`mov`、`mp4`、`m4v`、`mpeg`、`ogg`、`flv`
- 音视频时长不能超过 `6` 小时
- 文件大小不能超过 `6 GB`
> 说明:本 shortcut 只接收 `file_token`,不会直接读取本地文件内容,因此这些格式、时长和大小限制对应的是**原始上传文件**本身。若妙记生成失败,请先回查源文件是否满足上述要求。
## 核心约束
### 1. 必须提供 file_token
本接口不直接处理本地文件的上传,必须先使用 `drive +upload` 将文件上传到云空间(云盘/云存储)获取 `file_token`,然后再调用本接口。
### 2. 先上传,再生成妙记
推荐流程如下:
1. 使用 `lark-cli drive +upload --file <path>` 上传本地音视频文件到云空间(云盘/云存储)
2. 从返回结果中取出 `file_token`
3. 调用 `lark-cli minutes +upload --file-token <file_token>` 生成妙记
4. 如果目标是纪要、逐字稿、文字稿、撰写文字、总结、待办或章节,使用返回的 `minute_token`,继续调用 `lark-cli minutes +detail --minute-tokens <minute_token> --wait-ready`
> **边界说明**`minutes +upload` 本身只负责把文件转成妙记并返回 `minute_url`。纪要内容、逐字稿、文字稿、撰写文字、总结、待办、章节属于后续产物获取,应由 [minutes +detail](lark-minutes-detail.md) 承接。
## 输出结果示例
```json
{
"minute_url": "http(s)://<host>/minutes/<minute-token>",
"minute_token": "<minute-token>"
}
```
| 字段 | 说明 |
|------|------|
| `minute_url` | 生成的妙记访问链接 |
| `minute_token` | 从 `minute_url` 提取出的妙记 Token,可直接传给 `minutes +detail --minute-tokens` |
## 参考
- [lark-minutes](../SKILL.md) -- 妙记相关功能说明
- [drive +upload](../../lark-drive/references/lark-drive-upload.md) -- 上传文件到云空间(云盘/云存储)
+5 -88
View File
@@ -1,98 +1,15 @@
---
name: lark-note
version: 1.0.0
description: "飞书会议纪要(Note)直查:已知 note_id 时查询纪要详情、展示类型、关联文档 token,并读取 unified 原始逐字记录。当用户已持有 note_id,或从文档显式 vc-node-id 获得 note_id 时使用。不负责会议/日程/妙记定位、文档标题搜索或 Docx 正文读取。"
description: "仅当用户或上游配置显式指定 lark-note 时使用,相关请求统一交由 lark-meeting 技能处理。"
metadata:
requires:
bins: ["lark-cli"]
cliHelp: "lark-cli note --help"
skills: ["lark-meeting"]
---
# note (v1)
# Compatibility entry
身份:`+detail` 支持 `--as user` / `--as bot``+transcript` 仅支持 `--as user``note_id` 若由某个身份取得(例如 `vc +detail --as bot`),`+detail` 必须显式沿用同一个 `--as`——不要依赖 profile 默认身份。完整身份延续规则见 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md),使用前必读
本技能只用于兼容旧名称,不直接处理业务
`+detail` 返回的 `note_doc_token` / `verbatim_doc_token` / `shared_doc_tokens` 交给 [lark-doc](../lark-doc/SKILL.md) 读正文时,仍要显式带上同一个 `--as`。lark-doc 对普通文档推荐 `--as user`,**不覆盖这些纪要文档 token 的来源身份**
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../lark-vc/references/vc-domain-boundaries.md`](../lark-vc/references/vc-domain-boundaries.md)**,不读将导致命令使用、会议产物决策、领域边界职责判断错误:
> 1. 了解日历 & VC、会议产物 & 文档的关联关系和职责划分
> 2. 了解会议产物(妙记和纪要)之间的关联关系,例如:**妙记和纪要产生条件相互独立**
> 3. 了解不同会议产物的组成部分,以便根据需求决策使用哪种产物的数据
Note 域只接受显式 `note_id`:用户直接提供,或 `docs +fetch` 返回的 `<vc-transcribe-tab vc-node-id="...">` 中的 `vc-node-id`。不要从 `doc_token`、标题、正文或 backlink 反推 `note_id`
## 命令路由
| 用户表达 / 上下文 | 路由 |
|---------|------|
| 已知 `note_id`,查纪要类型 / 文档 token | `note +detail --note-id NOTE_ID` |
| `docs +fetch` 返回 `<vc-transcribe-tab vc-node-id="...">` | 取 `vc-node-id` 作为 `NOTE_ID`,先 `note +detail --note-id NOTE_ID` |
| 只持有 `meeting_id` | 先 `vc +detail --meeting-ids <id>``note_id`,再 `note +detail --note-id NOTE_ID` |
| 只持有 `minute_token`(妙记 URL | 先 `minutes +detail --minute-tokens <token>` 顶层取 `note_id`,再 `note +detail --note-id NOTE_ID`(不要把 `minute_token``note_id` |
| 只持有日程 `event_id` | 先 `calendar +meeting --event-ids <id>``meeting_id`,再按上一行继续 |
| 已知 `note_id`,读纪要正文 | `note +detail``docs +fetch --doc <note_doc_token>` |
| 已知 `note_id`,查 unified 原始记录 / 逐字稿 | `note +transcript --note-id NOTE_ID` |
| 只有自然语言纪要标题,用户要逐字稿 / 原始记录 / 谁说了什么 | 不进本 skill;先走文档搜索与 `docs +fetch`,拿到 `vc-node-id` 后再回来 |
## `note_display_type` 路由
| `note +detail` 结果 | 用户要逐字稿 / 原始记录时 |
|------|---------------|
| `normal` + `verbatim_doc_token` 非空 | `docs +fetch --doc <verbatim_doc_token>`(沿用 `+detail` 用的身份) |
| `unknown` + `verbatim_doc_token` 非空 | 先按独立文档处理;不要猜成 unified |
| `unknown` + 无逐字稿 token | 停止重试并说明无法确定逐字稿入口 |
| `unified` | `note +transcript --note-id <note_id>`(仅支持 `--as user` |
判别键是 `note_display_type`,不是 `verbatim_doc_token` 是否为空:unified 纪要也可能返回非空 `verbatim_doc_token`
> **bot + unified 的边界**`+transcript` 目前仅支持 `--as user`。如果 `+detail --as bot` 返回 `unified`,不要静默切到 `--as user` 继续——先停下来向用户说明"该纪要逐字稿只能以 user 身份读取",只有用户明确同意才切换身份重试。
## 关键字段
- `note_id`Note 域唯一入口。
- `note_display_type``unknown` / `normal` / `unified`
- `note_doc_token`:纪要正文文档,正文读取交给 [lark-doc](../lark-doc/SKILL.md)。
- `verbatim_doc_token`:普通纪要逐字稿文档;unified 逐字稿不按这个 token 路由。
## 不在本 Skill 范围
- 通过 `meeting_id` 定位纪要(`note_id`)→ [lark-vc](../lark-vc/SKILL.md)`vc +detail`)。
- 通过 `minute_token` 定位纪要(`note_id`)→ [lark-minutes](../lark-minutes/SKILL.md)`minutes +detail` 顶层返回 `note_id`)。
- 通过日程 `event_id` 定位会议(`meeting_id`) / 用户绑定纪要(`meeting_note`) → [lark-calendar](../lark-calendar/SKILL.md)`calendar +meeting`)。
- 自然语言纪要标题搜索 → [lark-drive](../lark-drive/SKILL.md) / [lark-doc](../lark-doc/SKILL.md)。
- Docx 正文读取 → [lark-doc](../lark-doc/SKILL.md)。
- 妙记基础信息与媒体文件 → [lark-minutes](../lark-minutes/SKILL.md)。
## Shortcuts
| Shortcut | 何时读 reference |
|----------|------|
| [`+detail`](references/lark-note-detail.md) | 需要解释输出字段或根据展示类型继续路由 |
| [`+transcript`](references/lark-note-transcript.md) | 需要拉取 unified 原始记录或处理本地输出文件 |
## 核心概念
- **会议纪要(Note)**:视频会议结束后生成的结构化文档,通过 `note_id` 标识。一个 Note 包含 AI 智能纪要文档、逐字稿文档和会中共享文档。
- **note_id**:纪要的唯一标识符,可通过 `vc +detail --meeting-ids` 获取。
- **AI 智能纪要(MainDoc)**:AI 生成的会议总结与待办,对应 `note_doc_token`
- **逐字稿(VerbatimDoc)**:会议的逐句发言记录,含说话人和时间戳,对应 `verbatim_doc_token`
- **共享文档(SharedDoc)**:会中投屏共享的文档,对应 `shared_doc_tokens`
## 核心场景
### 1. 通过 note_id 获取纪要文档 Token
1. 当用户已有 `note_id`,需要获取对应的 `note_doc_token``verbatim_doc_token``shared_doc_tokens` 时,使用 `note +detail`
2. `note_id` 通常来自 `vc +detail` 的返回结果。
3. 获取到文档 Token 后,可使用 `docs +fetch` 读取文档内容,或使用 `drive metas batch_query` 获取文档元信息。
```bash
# 1. 从会议获取 note_id(这里以 bot 身份为例)
lark-cli vc +detail --meeting-ids <meeting_id> --as bot
# 2. 用 note_id 拿文档 Token;沿用第 1 步的身份,不要省略 --as
lark-cli note +detail --note-id <note_id> --as bot
# 3. 读取纪要文档内容;同样沿用第 1 步的身份
lark-cli docs +fetch --doc <note_doc_token> --doc-format markdown --as bot
```
**MUST 完整读取 [`../lark-meeting/SKILL.md`](../lark-meeting/SKILL.md),并按照其中的路由和行动指南执行。**
@@ -1,29 +0,0 @@
# note +detail
通过 `note_id` 查询会议纪要详情,获取下挂文档 Token(AI 智能纪要、逐字稿、会中共享文档)。只读,支持 `--as user` / `--as bot`。bot 身份下能否读到数据取决于应用对纪要主文档是否有 view 权限。
## 命令
```bash
lark-cli note +detail --note-id <note_id>
lark-cli note +detail --note-id <note_id> --as bot
```
## `note_id` 来源
- 可以来自用户直接给出的 `note_id`
- 如果入口是文档,先由 [lark-doc](../../lark-doc/SKILL.md) 读取 Docx;只有 `<vc-transcribe-tab vc-node-id="...">``vc-node-id` 可以作为 `note_id`
- 没有 `vc-node-id` 时,不要从 `doc_token`、标题、正文或 backlink 反推 `note_id`
## 输出后的路由
| detail 字段 | 后续动作 |
|---------|---------|
| `note_doc_token` | 读纪要正文 / 总结 / 待办 / 章节:`docs +fetch --doc <note_doc_token>` |
| `note_display_type=normal` + `verbatim_doc_token` | 读逐字稿:`docs +fetch --doc <verbatim_doc_token>` |
| `note_display_type=unknown` + `verbatim_doc_token` | 先按普通独立逐字稿文档读取;不要猜成 unified |
| `note_display_type=unified` | 读逐字稿 / 原始记录:转 [`note +transcript`](lark-note-transcript.md)(仅支持 `--as user` |
判别键是 `note_display_type`。即使 unified 纪要返回了非空 `verbatim_doc_token`,逐字稿仍按 unified 路由。
> **bot + unified 的边界**:如果本命令用 `--as bot` 拿到 `note_display_type=unified``note +transcript` 只支持 `--as user`,不能直接沿用 bot 身份。停下来向用户说明这个边界,只有用户明确同意才切到 `--as user` 继续,不要静默切换身份。
@@ -1,25 +0,0 @@
# note +transcript
只在 `note +detail` 已确认 `note_display_type=unified` 时使用。普通纪要逐字稿是独立 Docx 文档,应回到 [lark-doc](../../lark-doc/SKILL.md) 读取 `verbatim_doc_token`
只支持 `--as user`,不支持 `--as bot`。如果 `note +detail --as bot` 返回 `unified`,不要在这里静默省略 `--as` 或改用 user 身份继续——先停下来向用户说明"该纪要逐字稿只能以 user 身份读取",只有用户明确同意才切换身份重试。
```bash
lark-cli note +transcript --note-id NOTE_ID
```
## 行为契约
- CLI 会先校验该 Note 是否为 `unified`;不是 unified 时不拉取 transcript。
- CLI 内部自动翻页并拼接完整内容;任一页失败时整体报错,不保存半截 transcript。
- 默认保存到 `./notes/{note_id}/unified_transcript.md``--transcript-format plain_text` 时保存为 `.txt`
- 目标文件已存在时会失败;用户明确要覆盖时才加 `--overwrite`
## 何时不要用
| 场景 | 正确路由 |
|------|---------|
| 只有纪要文档标题 | 先文档搜索,再 `docs +fetch`;有 `vc-node-id` 才回 Note 域 |
| 只有 Docx URL / `doc_token` | 先 `docs +fetch`;不要从 `doc_token` 反推 `note_id` |
| `note_display_type=normal` | `docs +fetch --doc <verbatim_doc_token>` |
| `note_display_type=unknown``verbatim_doc_token` 非空 | 先按独立逐字稿文档读取 |
+1 -1
View File
@@ -31,7 +31,7 @@ shortcut 名称只能来自本 Skill 的 Shortcut 表或 `lark-cli task --help`
> **用户身份识别**:在用户身份(user identity)场景下,如果用户提到了“我”(例如“分配给我”、“由我创建”),请默认获取当前登录用户的 `open_id` 作为对应的参数值。
> **术语理解 — 待办 disambiguation(必读)**
> - 用户提到「待办 / todo / 任务」时,**先判断归属**,不要默认走本 skill。
> - **走 [lark-minutes](../lark-minutes/SKILL.md) 的 `minutes +todo`**(禁止本 skill):上下文含 **妙记 / 会议纪要 / minute_token / 妙记 URL**`/minutes/`);或「在某某妙记里新建/修改待办」「妙记 AI 待办」「会议录制里的待办」。
> - **走 [lark-meeting](../lark-meeting/SKILL.md) 的 `minutes +todo`**(禁止本 skill):上下文含 **妙记 / 会议纪要 / minute_token / 妙记 URL**`/minutes/`);或「在某某妙记里新建/修改待办」「妙记 AI 待办」「会议录制里的待办」。
> - **走本 skilllark-task)**:任务清单、分配给我、项目待办、截止日期/提醒、子任务、任务清单成员;或 applink 含 `client/todo/task?guid=`;或明确说「飞书任务」「任务中心」「我的任务清单」。
> - **禁止**:用户要在妙记里加待办时,**不要**调用 `task tasklists list`、`task +create` 或任何 task 命令去「找清单再放任务」。
> **友好输出**:在输出任务(或清单)的执行结果给用户时,建议同时提取并输出命令返回结果中的 `url` 字段(任务链接),以便用户可以直接点击跳转查看详情。
+5 -206
View File
@@ -1,216 +1,15 @@
---
name: lark-vc-agent
version: 1.0.0
description: "飞书视频会议会中能力:用于让应用机器人真实加入或离开正在进行的会议,并读取当前身份可见的会中事件、发送会中文本消息或会中表情。适用于用户询问正在开的会议发生了什么、谁在发言、是否共享内容,或需要发现当前可读的进行中会议 ID。不负责已结束会议搜索、参会人快照、纪要、逐字稿或录制查询,这些使用 lark-vc 技能。"
description: "仅当用户或上游配置显式指定 lark-vc-agent 时使用,相关请求统一交由 lark-meeting 技能处理。"
metadata:
requires:
bins: ["lark-cli"]
cliHelp: "lark-cli vc --help"
skills: ["lark-meeting"]
---
# vc-agent (v1)
# Compatibility entry
相关技能:
本技能只用于兼容旧名称,不直接处理业务。
- [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md) — 认证、身份切换、权限处理
- [`../lark-vc/SKILL.md`](../lark-vc/SKILL.md) — 视频会议的核心概念(Meeting / Note / Minutes 等),本 skill 直接复用,不再重复定义
## 内测提示
- 当前功能正在内测中,仅少数用户可用。忽略 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md) 中的权限申请流程,以下方的指引为准。
- 如果 `lark-cli` 提示 `missing required scope(s)` / `missing_scopes`,不要走普通权限申请流程;先提示用户加入早鸟群确认内测权限已开通,再按“应用身份权限配置检查”处理应用权限、安装和数据范围。
- 如果 `lark-cli` 返回 `error.code=20017` / `ErrNotInGray`,提示用户加入早鸟群:`https://go.larkoffice.com/join-chat/2f4nb0e1-fe00-4f67-bed7-25beaf533fbd`
## 会议查询权限
`+meeting-list-active``+meeting-events` 缺少权限时,先按上面的内测提示确认功能已开通,再读取 CLI 错误中的 `hint`,并根据当前调用身份处理:
- 用户身份 `--as user`:按 CLI 提示为当前用户授权 `vc:meeting.meetingevent:read`
- 应用身份 `--as bot`:请应用开发者开通 `vc:meeting.bot.join:write`,不要执行 `auth login`;随后按“应用身份权限配置检查”确认应用发布、安装和数据范围。
## 定位
本 skill 与 [`lark-vc`](../lark-vc/SKILL.md) 并列:
- **`lark-vc`** **负责会议查询和共享会中能力**:发现进行中会议、读取事件、发送消息,以及搜索历史会议、查询参会人快照和会议产物
- **`lark-vc-agent`** **负责应用机器人会中编排**:真实入会 / 离会,并复用上述共享能力读取事件或发送消息
按此分工路由,避免两个 skill 语义混淆。
| 用户意图示例 | 应路由到 |
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| "帮我入会 123456789"、"代我参会"、"让机器人进会旁听" | **本 skill** `+meeting-join` |
| "会议现在还开着,谁刚加入了"、"会议里谁在发言"、"有人共享屏幕吗"**进行中会议**) | **本 skill** `+meeting-events` |
| "我/某个用户现在在哪个会里"、"给我找当前可拉事件的 meeting_id" | **本 skill** `+meeting-list-active` |
| "在会里发一句 xx"、"提示大家 xx"、"反馈听不到/看不到/声音清楚/效果不错"(**进行中会议**) | **本 skill** `+meeting-message-send` |
| "退出会议"、"让机器人离开" | **本 skill** `+meeting-leave` |
| "昨天那场会有谁参加过"、"搜昨天的会"、"查纪要/逐字稿/录制" | [`lark-vc`](../lark-vc/SKILL.md) |
| "帮我参会,结束后把纪要发到群" 等跨阶段场景 | 按序编排:本 skill(入会 → 读事件)→ 会议结束后用 [`lark-vc`](../lark-vc/SKILL.md) / [`lark-minutes`](../lark-minutes/SKILL.md) 拉纪要 → [`lark-im`](../lark-im/SKILL.md) 发群 |
## 身份路由
不要向用户暴露内部身份缩写;对用户只说“用户身份”或“应用身份”。
| 场景 | 使用身份 | 关键规则 |
| ---- | -------- | -------- |
| 查询当前登录用户正在参加的会议 | `--as user` | 不传 `--user-id`;拿到的 `meeting_id` 后续继续用 `--as user` 读事件 |
| 查询目标用户且应用机器人也在会中的会议 | `--as bot --user-id <user_open_id>` | `--user-id` 必须是 `ou_...`;拿到的 `meeting_id` 后续继续用 `--as bot` 读事件 |
| 用户明确要求应用机器人入会/旁听/代参会 | `--as bot` | 这是写操作,会真实产生入会记录;返回的 `meeting.id` 后续继续用 `--as bot` |
硬规则:`meeting_id` 从哪种身份路径拿到,后续 `+meeting-events` / `+meeting-message-send` 就沿用哪种身份,除非用户明确要求切换场景(例如从“仅查询我当前会”改成“让应用机器人入会旁听”)。
## 核心场景
### 1. 加入正在进行的会议(写操作)
1. 只有用户明确表达"让 Agent **真实入会**"(参会机器人、会中助手、代为旁听、代参会)时才用 `+meeting-join`。只是查数据不要入会。
2. `+meeting-join --meeting-number` 只接受 **9 位纯数字**会议号,不是会议链接整串、也不是 `meeting_id`。如果用户只是给了 9 位会议号并询问会中内容,先按 `+meeting-list-active` 的会议号匹配流程找 `meeting_id`,不要直接入会。
3. 返回体中的 `meeting.id` **必须立刻记录**——后续 `+meeting-events` / `+meeting-leave` 都靠它,**不能用 9 位会议号替代**。
4. 入会对所有参会人可见,执行前核实 9 位会议号来源,避免误入错会。
5. 使用应用身份 `--as bot` 执行真实入会;不要用当前登录用户身份尝试让应用机器人入会。
6. 若入会失败,优先查看 `+meeting-join` reference 的错误排查段落,重点确认会议号、密码、会议状态、等候室 / 审批以及会议是否禁止当前身份加入。
### 2. 感知会中事件(读操作)
1. 用户要看"会议里正在发生什么"(参会人加入/离开、聊天、转写、屏幕共享)时,用 `+meeting-events`
2. 输入是 **`meeting_id`**(长数字 ID),不是 9 位会议号。
3. 不依赖默认身份。`meeting_id` 来自用户身份发现时,继续用 `--as user`;来自应用身份发现或 `+meeting-join` 时,继续用 `--as bot`。身份不一致会导致空结果或权限错误。
4. **不能做会后复盘**,**不能替代参会人快照查询**。如果会议已结束:
- 先用 `lark-cli vc +detail --meeting-ids <meeting.id>` 获取会议产物信息。
- 再根据 `note_id``minute_token` 和用户意图,按 [`lark-vc`](../lark-vc/SKILL.md) 的产物决策读取正文、逐字稿或妙记。
- 想看参会人快照:用 `vc meeting get --with-participants`(见 [`lark-vc`](../lark-vc/SKILL.md)
5. **默认必须使用** **`--page-all`**,除非用户明确要求“只查一页”,或确实需要控制返回体大小。
6. 命令默认输出结构化事件契约:`meeting``identity``events``warnings``has_more``page_token``identity` 表示当前读取身份,事件 actor 含 `participant_type``role` 和可读 `label`,事件细节保留在 `payload`
7. 输出格式默认优先 `--format pretty`(时间线更易读,并带当前身份标签);需要稳定字段做结构化处理时用 `--format json`;需要流式消费事件时用 `--format ndjson`
8. **必须识别分页信号**:只要响应里出现 `has_more=true`、pretty 里的 `more available`,或返回了非空 `page_token`,就不能把当前结果当作完整事件流;默认应继续分页,或明确告诉用户当前只是部分结果。
9. 保留响应里的 `page_token`,下次增量拉取直接续,不要从头再拉。
10. **只要你是基于** **`+meeting-events`** **来回答一场正在进行中的会议内容,就不能直接复用旧结果。** 无论用户是在问“现在/刚刚/最新”的状态,还是让你“总结一下这个会议讲什么”,都必须先重新拉一次当前事件流,确认拿到的是最新信息,再基于最新结果回答。只有在用户明确要求基于某次历史快照继续分析时,才可以复用旧结果。
11. **会中聊天 / 互动转发到 IM 时基于 JSON 事件构造 IM post。** `chat_received_items[].message_type == 3` 表示会中 reaction;构造 IM post 时,先用 [`lark-im` reaction emoji 白名单](../lark-im/references/lark-im-reactions.md) 判断同一 item 的 `content`:白名单内才写成 Feishu post `emotion` 节点,不在白名单内则保留原始 key 并写成文本节点,例如 `[CanNotSee]`。普通聊天按文本发送。不要从 pretty/Markdown 重新拼消息,也不要把整条消息退化成纯文本;只降级非法 reaction key。用户已说“发给我 / 推送给我 / 发到我的单聊”时,默认用 bot 身份直接发当前用户;收件人不明确时只补问收件人。
12. 用户直接问“这个会议讲了什么 / 现在讲到哪了”且上下文没有明确 `meeting_id` 时,先用用户身份发现当前会议;如果用户明确要求应用机器人视角,或上下文已经是应用机器人参会流程,再用应用身份发现。若返回多个会议,展示候选并让用户选择。
13. 默认用户身份路径未发现当前会议时,改用 [`lark-vc`](../lark-vc/SKILL.md) 的 `+search` 查询当天最近结束的会议;仍无结果时询问会议时间、主题或会议号,不自行扩大时间范围。应用机器人视角未发现当前会议时,按当前身份解释空结果,不自动查询历史会议或真实入会。
14. 用户直接提供 **9 位会议号** 并询问会中事件/会议内容时,默认把它当作 active meeting 的筛选条件:先按当前身份查 active meetings,并在返回里匹配 `meeting_no == <9位会议号>`;匹配到唯一会议后取长数字 `meeting_id`,再用同一身份查事件。只有用户明确要求“入会 / 让应用机器人旁听 / 代我参会”时才改用 `+meeting-join`
#### 文档上下文事件
`event_type == "document_context_changed"` 时,结构化消费按 `payload.document_context_changed_items` 原序读取;CLI pretty timeline 与其他事件一致,按 item `time` 排序。每个 item 只接受一个 `comment_focus``section_location``element_preview`;零个、多个、字段缺失或未知值不生成 pretty 条目,但保留事件 `payload` 和原标识,不猜字段别名。
| context | 消费规则 |
| --- | --- |
| `comment_focus` | 先按完整事件流中的 `magic_share_started/ended` 维护 `share_id -> share_doc` 共享会话映射,再用当前 item 的 `share_id` 精确关联文档;禁止退化为“最近一次共享”猜测。`document_context_changed` item 自带的 `share_doc` 当前不提供文档信息,只保留在 raw payload,不作为解析来源。仅当 `focused=true`、单个 `comment_id` 和由开始共享事件解析出的有效文档 URL 均存在时,用 `drive +batch-query-comments` 精确查询该 ID;严格匹配、回复分页与失败终止条件见 reference。`focused=false` 表示清除焦点,零评论调用。 |
| `section_location` | 从当前 item 的 `parent_titles/title` 按原序派生 pretty timeline 中的章节路径;JSON/NDJSON 继续只保留原始 payload,不新增事件顶层 `section_path`。不得根据 `level` 反转、截断或补造路径,也不调用文档 API。 |
| `element_preview` | 只有用户明确要求预览且 `action=open` 时路由:`element_type=image` 使用 `docs +media-preview --token <element_token> --output <用户选择路径>``element_type=whiteboard` 使用 `docs +media-download --type whiteboard --token <element_token> --output <用户选择路径>``close`、未知 type/action、缺 token 或无明确预览意图均零调用;禁止把未知 `element_type` 透传给 `--type`,禁止自动选择覆盖路径。 |
`vc +meeting-events` 始终只读,不因评论或元素上下文自动调用 Drive/Docs,也不写文件。`share_id` 无法关联、评论 API/权限失败或 reply 游标为空/重复时,明确标记结果为未解析或 partial,并保留 `share_id``share_doc``comment_id``element_token``block_id` 和 raw payload,给出可重试的精确命令;不要用“最近一次共享”、全量评论扫描或自动下载兜底。完整命令与终止条件见 [`+meeting-events` reference](../lark-vc/references/lark-vc-meeting-events.md#文档上下文事件消费)。
JSON/NDJSON 的单事件 envelope 始终只使用既有 `event_id/event_type/event_time/actors/payload` 字段;不得为 `document_context_changed` 单独增加顶层 `summary/section_path` 或新的 `derived` 层。结构化消费从 `payload.document_context_changed_items[]` 读取,pretty 仅作可读派生展示。
### 3. 发送会中文本或会中表情(写操作)
1. 用户明确要求在当前进行中的会议里发送提示、说明、会中表情,或反馈“听不到 / 看不到 / 声音清楚 / 效果不错”时,用 `+meeting-message-send`
2. 输入是长数字 `meeting_id`,不是 9 位会议号。若用户只给 9 位会议号,先按当前身份执行 `+meeting-list-active` 并按 `meeting_no` 匹配,匹配到唯一会议后再发送;不要为了发消息自动入会。发消息只需 `meeting_id`,不要先查 `+detail`
3. 身份必须延续:`meeting_id` 来自用户身份发现,就继续 `--as user`;来自应用身份发现或应用机器人入会,就继续 `--as bot`
4. 文本消息使用 `--text`;会中表情 / 反馈使用 `--emoji-type``--emoji-type` 必须从 reference 里的完整列表中选择,大小写敏感。
5. 支持普通 Feishu reaction emoji(如 `LOVE``SMILE``THUMBSUP`)和 4 个 VC 反馈 key`VC_CanNotSee``VC_NoSound``VC_LooksGood``VC_SoundsClear`)。
6. 不要编造列表外的 `emoji_type`,也不要把 natural language 硬编码成不存在的 key;如果用户只给语义,可在完整列表中选择最接近的 key,无法判断时先确认。
7. 该命令只暴露会中文本和会中表情,不作为“发送绑定群消息”的默认能力;如果用户明确要发群聊,请路由到 [`lark-im`](../lark-im/SKILL.md)。
8. 若使用应用身份发送,应用机器人必须在会中;若使用用户身份发送,当前用户必须正在该会议中。权限错误时按“应用身份权限配置检查”或“用户身份被拒绝时”处理。
示例:
```bash
lark-cli vc +meeting-message-send --as user --meeting-id <meeting_id> --text "稍等,我在看文档"
lark-cli vc +meeting-message-send --as bot --meeting-id <meeting_id> --msg-type reaction --emoji-type LOVE
lark-cli vc +meeting-message-send --as bot --meeting-id <meeting_id> --msg-type reaction --emoji-type VC_NoSound
```
### 4. 离开会议(写操作)
1. 只有用户明确要求机器人退出 / 离开 / 结束参会时,才用应用身份执行 `+meeting-leave --as bot --meeting-id <长数字 meeting_id>`;不应因任务完成而执行离会。
2. `--meeting-id` **必须**是长数字会议 ID,通常来自 `+meeting-join` 返回的 `meeting.id`,也可以来自应用身份 `+meeting-list-active` 返回的 `meeting_id`。如果来自 list-active,必须确认应用机器人当前就在该会中。**不接受 9 位会议号**
3. 离会**立即生效**,机器人从会议的参会人列表中消失,对其他参会人可见;若需要重新入会,再跑一次 `+meeting-join` 即可(非真正"不可逆")。
4. 使用与入会或 active meeting 发现相同的应用身份离会。
### 5. 获取当前可用的进行中会议 ID(读操作)
1. `+meeting-list-active` 用来发现当前进行中的会议,并拿到后续 `+meeting-events` 需要的长数字 `meeting_id`
2. 用户身份:`lark-cli vc +meeting-list-active --as user --format json`,用于发现当前登录用户正在参加的会议;后续 `+meeting-events` 继续 `--as user`
3. 应用身份:`lark-cli vc +meeting-list-active --as bot --user-id <user_open_id> --format json``--user-id` 必须是目标用户 open_id,即 `ou_...`;返回该用户当前正在参加且应用机器人也在会中的会议。它不是全量会议搜索接口。后续 `+meeting-events` 继续 `--as bot`
4. 如果返回空,先按当前身份解释:用户身份下表示当前用户没有可见的进行中会议;应用身份下表示没有找到“目标用户在会中且应用机器人也在会中”的当前会。
5. 如果返回多个会议,不要自动任选一个;按 `meeting_title` / `meeting_no` / `meeting_id` 展示候选,等待用户明确选择后再调用 `+meeting-events`
6. 如果用户给了 9 位会议号,先在 active meeting 结果中按 `meeting_no` 匹配。匹配失败时,不要自动入会;只有用户明确要求应用机器人真实入会时,才询问或执行 `+meeting-join`
### 6. Agent 参会示范
```bash
# 1. 入会,捕获 meeting.id
AS=bot
JOIN=$(lark-cli vc +meeting-join --as "$AS" --meeting-number 123456789 --format json)
MID=$(echo "$JOIN" | jq -r '.data.meeting.id')
# 2. 会中轮询事件
# 沿用入会身份;默认用 --page-all 拉全当前可见事件;下次增量优先复用 page_token
# 典型间隔 10-30 秒
lark-cli vc +meeting-events --as "$AS" --meeting-id "$MID" --page-all --format pretty
# 3. 会后可选:进入 lark-vc 获取会议产物信息,再按 note_id / minute_token 决策读取
lark-cli vc +detail --meeting-ids "$MID"
```
如果用户随后明确要求退出 / 离开 / 结束参会,再单独调用 `lark-cli vc +meeting-leave --as bot --meeting-id "$MID"`
如果已经知道目标用户 `open_id`,且 bot 已在会中,也可以先发现当前会:
```bash
lark-cli vc +meeting-list-active --as bot --user-id <user_open_id> --format json
lark-cli vc +meeting-events --as bot --meeting-id <id> --page-all --format pretty
```
如果只是回答当前登录用户所在会议发生了什么,使用用户身份一路查:
```bash
lark-cli vc +meeting-list-active --as user --format json
lark-cli vc +meeting-events --as user --meeting-id <meeting_id> --page-all --format pretty
```
## Shortcuts
Shortcut 是对常用操作的高级封装(`lark-cli vc +<verb> [flags]`)。
| Shortcut | 类型 | 说明 |
| --------------------------------------------------------------- | -- | -------------------------------------------------------------------------- |
| [`+meeting-join`](references/lark-vc-agent-meeting-join.md) | 写 | Join an in-progress meeting by 9-digit meeting number |
| [`+meeting-list-active`](../lark-vc/references/lark-vc-meeting-list-active.md) | 读 | List active meetings and discover meeting_id for event reads |
| [`+meeting-events`](../lark-vc/references/lark-vc-meeting-events.md) | 读 | List meeting events visible to the current identity (participant, transcript, chat, share, document context) |
| [`+meeting-message-send`](../lark-vc/references/lark-vc-meeting-message-send.md) | 写 | Send an in-meeting text message or reaction emoji |
| [`+meeting-leave`](references/lark-vc-agent-meeting-leave.md) | 写 | Leave a meeting by meeting\_id |
- [`+meeting-join`](references/lark-vc-agent-meeting-join.md):入参格式、写操作可见性风险、入会失败排查。
- [`+meeting-list-active`](../lark-vc/references/lark-vc-meeting-list-active.md):用户身份和应用身份的不同返回范围。
- [`+meeting-events`](../lark-vc/references/lark-vc-meeting-events.md)`meeting_id` 来源、身份延续、分页和错误码(10005 / 20001 / 20002)。
- [`+meeting-message-send`](../lark-vc/references/lark-vc-meeting-message-send.md):会中文本、完整 `emoji_type` 列表、身份延续和写操作风险。
- [`+meeting-leave`](references/lark-vc-agent-meeting-leave.md)`meeting_id` 的来源与写操作可见性。
## 应用身份权限配置检查
应用身份 `--as bot``no permission``missing required scope(s)``missing_scopes``ErrNotInGray``20017` 时,不要引导用户执行 `auth login`。按顺序检查:
1. 确认内测权限后,按 CLI 错误中的 `hint` 处理;返回 `console_url` 时将其原样提供给用户。
2. 应用已发布并安装到当前租户。
3. 开放平台“权限可访问的数据范围”已开通并保存。
4. 数据范围选择“按条件筛选”,条件配置为:**会议的归属者 包含 与应用的可用范围一致**。
5. 如果 scope、安装和数据范围都正确,仍返回 `ErrNotInGray` / `20017`,再按 VC Agent 内测 privilege / 灰度白名单处理,提示加入早鸟群或联系平台同学开通。
## 用户身份被拒绝时
用户身份 `--as user` 调用 `+meeting-list-active``+meeting-events` 报普通 scope 缺失时,按“会议查询权限”处理;其他 shortcut 的 scope 缺失按各自 CLI `hint` 处理。普通 scope 缺失不表示接口不支持用户身份,只有 CLI 明确表明当前接口不支持用户身份访问时,才按用户意图切换处理:
1. 如果用户只是查询当前登录用户所在的进行中会议,说明当前接口链路不支持用户身份访问,改用应用身份流程;需要目标用户 open_id,并要求应用机器人已在会中或先按用户确认执行入会。
2. 如果用户明确要求应用机器人入会、旁听、代参会或读取应用机器人可见事件,直接切到 `--as bot`,并按上面的应用身份权限配置检查处理。
## 延伸
- 查已结束会议、参会人快照、搜索历史会议 → [`lark-vc`](../lark-vc/SKILL.md)
- 会议纪要、逐字稿 → [`lark-vc`](../lark-vc/SKILL.md) 的 `+detail`
- 妙记产物(AI 总结 / 转写 / 章节)→ [`lark-minutes`](../lark-minutes/SKILL.md)
- 会后把产物发到群 / 私聊 → [`lark-im`](../lark-im/SKILL.md)
- 认证、身份切换、scope 管理 → [`lark-shared`](../lark-shared/SKILL.md)
**MUST 完整读取 [`../lark-meeting/SKILL.md`](../lark-meeting/SKILL.md),并按照其中的路由和行动指南执行。**
+5 -205
View File
@@ -1,215 +1,15 @@
---
name: lark-vc
version: 1.0.0
description: "飞书视频会议:查询进行中的会议列表(含会议 ID)、读取会中实时内容(发言、聊天、共享等)、发送会中消息,以及搜索历史会议、查询会议纪要(总结/待办/章节/逐字稿)和参会人快照。Agent 真实入会/离会走 lark-vc-agent;查询未来日程走 lark-calendar。"
description: "仅当用户或上游配置显式指定 lark-vc 时使用,相关请求统一交由 lark-meeting 技能处理。"
metadata:
requires:
bins: ["lark-cli"]
cliHelp: "lark-cli vc --help"
skills: ["lark-meeting"]
---
# vc (v1)
# Compatibility entry
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md),其中包含认证、权限处理**
本技能只用于兼容旧名称,不直接处理业务。
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`references/vc-domain-boundaries.md`](references/vc-domain-boundaries.md)**,不读将导致命令使用、会议产物决策、领域边界职责判断错误:
> 1. 了解日历 & VC、会议产物 & 文档的关联关系和职责划分
> 2. 了解会议产物(妙记和纪要)之间的关联关系,例如:**妙记和纪要产生条件相互独立**
> 3. 了解不同会议产物的组成部分,以便根据需求决策使用哪种产物的数据
> 4. 了解会议总结、分析和信息提取的标准流程
## 身份
身份是跨命令工作流的状态,不是单条命令的局部参数:一旦某个 ID(如 `note_id``minute_token`)由某个身份取得,后续消费它的命令(包括跨到 lark-minutes / lark-note / lark-doc)必须显式沿用相同 `--as`;不要依赖 profile 默认身份,也不要为绕过权限错误切换身份。完整规则见 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md) 的「身份延续」。
**本链路的身份策略覆盖到最后一跳读正文**`vc +detail``note +detail``docs +fetch --doc <note_doc_token> / <verbatim_doc_token>` 全程用同一个 `--as`。[lark-doc](../lark-doc/SKILL.md) 对普通文档推荐 `--as user`,**不覆盖本链路取得的纪要文档 token**;读正文时不要因此切回 user。
本 skill 默认使用 `--as user``+detail``+recording``meeting get``+meeting-list-active``+meeting-events``+meeting-message-send` 也支持 `--as bot``+meeting-events``+meeting-message-send` 必须沿用 `meeting_id` 的来源身份。`+search` 仅支持 `--as user`
```bash
# BAD — 查昨天的会议用 calendar,会漏掉即时会议
lark-cli calendar +search-event --query "站会" --start <start_time> --end <end_time>
# GOOD — 查已结束的会议用 vc +search
lark-cli vc +search --query "站会" --start <start_time> --end <end_time>
```
## Shortcuts (推荐优先使用)
| Shortcut | 说明 |
|----------|------|
| [`+search`](references/lark-vc-search.md) | 搜索历史会议记录(需至关键词、时间范围、组织者、参与者、会议室少一个筛选条件) |
| [`+detail`](references/lark-vc-detail.md) | 通过 meeting-ids 获取会议详情,包括 note_id 和 minute_token |
| [`+recording`](references/lark-vc-recording.md) | 通过 meeting-ids 或 calendar-event-ids 查询 minute_token |
| [`+meeting-list-active`](references/lark-vc-meeting-list-active.md) | 查询当前身份可见的进行中会议并获取 `meeting_id` |
| [`+meeting-events`](references/lark-vc-meeting-events.md) | 读取当前身份可见的会中事件 |
| [`+meeting-message-send`](references/lark-vc-meeting-message-send.md) | 发送会中文本或 reaction |
- 使用任何 Shortcut 前,必须先读其对应 reference 文档。
## 意图路由
| 用户意图 | 路由到 |
|----------|--------|
| 查"昨天的会议""上周的会""已结束的会议" | 本 skill`+search`,含即时会议) |
| 查日历/日程或未来时间的会议 | [lark-calendar](../lark-calendar/SKILL.md) |
| 查"今天有哪些会议" | `vc +search`(已结束)+ lark-calendar(未开始),合并展示 |
| 查询进行中的会议、会中事件或发送会中消息 | 本 skill 的 `+meeting-list-active` / `+meeting-events` / `+meeting-message-send`,也可由 [lark-vc-agent](../lark-vc-agent/SKILL.md) 编排 |
| 用户询问会议内容,但未提供 `meeting_id`,也未明确指向已结束会议 | 先用 `+meeting-list-active` 查询进行中的会议;无结果时,再用 `+search` 查询当天最近结束的会议;仍无结果时询问会议时间、主题或会议号,不自行扩大时间范围 |
| 只按自然语言标题查"xx 纪要的逐字稿 / 原始记录 / 谁说了什么" | 先到 [lark-drive](../lark-drive/SKILL.md) / [lark-doc](../lark-doc/SKILL.md);仅在已拿到 `note_id` / `vc-node-id` 后再到 [lark-note](../lark-note/SKILL.md) |
| Agent 真实入会/离会 | [lark-vc-agent](../lark-vc-agent/SKILL.md) |
| 妙记信息/时长/封面/链接 | 先走 `vc +detail``vc +recording` 获取 `minute_token`,再用 [lark-minutes](../lark-minutes/SKILL.md) 的 `minutes get` |
| 本地音视频文件转纪要/逐字稿 | 先走 [lark-minutes](../lark-minutes/SKILL.md) 上传,再用 `minutes +detail --minute-tokens` |
## 核心概念
- **视频会议(Meeting)**:飞书视频会议实例,通过 meeting_id 标识。已结束的会议支持通过关键词、时间段、参会人、组织者、会议室等条件搜索(见 `+search`)。
- **会议纪要(Note)**:视频会议结束后生成的结构化文档,通过 `note_id` 标识,包含纪要文档(总结、待办)和逐字稿文档。`note_display_type` 区分**普通纪要(`normal`**和 **unified 纪要**;已知 `note_id` 的直查与 unified 原始记录请用 [lark-note](../lark-note/SKILL.md)。
- **妙记(Minutes)**:来源于飞书视频会议的录制产物或用户上传的音视频文件,支持视频/音频的转写,包含总结、待办、章节和文字记录,通过 minute_token 标识。妙记带有**原始会议录制视频**,会后**不会自动授权给参会人**,需管理员授权或参会人主动申请;而智能纪要及其逐字稿会后自动授权给参会人。
- **纪要文档(MainDoc)**:AI 智能纪要的主文档,包含 AI 生成的总结和待办,对应 `note_doc_token`
- **用户会议纪要(MeetingNotes)**:用户主动绑定到日程的纪要文档,对应 `meeting_note`。需先通过 [`calendar +meeting`](../lark-calendar/references/lark-calendar-meeting.md) 由 `event_id` 获取。
- **逐字稿(VerbatimDoc)**:会议的逐句文字记录,包含说话人和时间戳。
## 产物选择决策
| 用户意图 | 必须读取的产物 | 禁止 |
|---------|-------------|------|
| 提炼/总结/重新总结/整理会议内容/回顾会议 | 为降低 token 消耗,非必须不得获取 AI 纪要。必须使用原始对话记录(按下方逐字稿路由取得),基于原始对话独立分析。两类产物都存在且用户未指定时,默认用智能纪要的逐字稿;用户明确要妙记时才用妙记文字记录(Transcript) | 禁止直接搬运 AI 纪要(`note_doc_token`)的总结作为最终输出 |
| 查看待办/章节 | 默认 AI 纪要(`note_doc_token`);仅存在妙记或用户明确要妙记时用妙记产物 — AI 待办更友好(含提出人和负责人),章节按话题划分更结构化 | — |
| 查看纪要链接/文档地址 | 仅返回文档链接,无需读取内容 | — |
| 直接看 AI 总结结果 | AI 纪要(`note_doc_token` | — |
| 谁说了什么/完整发言记录 | 原始对话记录(按下方逐字稿路由取得) | — |
> **智能纪要 vs 妙记的选择规则**(总结/待办/逐字稿等重复产物通用):只存在一类 → 用存在的那类;两类都存在且用户明确指定(如"看妙记逐字稿")→ **语义指向哪个走哪个,不要改道**;两类都存在但用户未指定 → **默认智能纪要及其逐字稿**(会后自动授权给参会人,访问门槛低于含原始录制视频、需申请授权的妙记)。完整说明见 [`references/vc-domain-boundaries.md`](references/vc-domain-boundaries.md) 的「产物选择决策」。
> **逐字稿路由**:先用 `vc +detail` 拿到 `note_id`,再 [`note +detail`](../lark-note/SKILL.md) 看 `note_display_type`**不要只看 `verbatim_doc_token` 是否为空**。具体路由以 [lark-note](../lark-note/SKILL.md) 的 `note_display_type` 规则为准。
>
> **为什么"提炼/总结"必须从原始对话记录出发?** AI 纪要是模型对会议的二次压缩,可能遗漏讨论细节、争论过程和隐含决策。用户要求"提炼"或"重新总结"时,期望的是基于原始对话的独立分析,而非对 AI 产物的重新排版。
## 核心场景
### 1. 搜索会议记录
1. 仅支持搜索已结束的会议,对于还未开始的未来会议,需要使用 lark-calendar 技能。
2. 仅支持使用关键词、时间段、参会人、组织者、会议室等筛选条件搜索会议记录,对于不支持的筛选条件,需要提示用户。
3. 搜索结果存在多条数据时,务必注意分页数据获取,不要遗漏任何会议记录。
4. 只有自然语言纪要标题、没有会议线索时,不要把标题当会议关键词;按上方意图路由切到文档搜索。
### 2. 整理会议纪要
> 在选择读取哪个产物前,先确认你理解 AI 总结链路 vs 录制链路的区别。如不确定,先读 [`references/vc-domain-boundaries.md`](references/vc-domain-boundaries.md)。
1. 整理纪要文档时默认给出纪要文档、逐字稿、妙记链接即可,无需读取纪要文档或逐字稿内容。
2. 用户明确需要获取总结、待办、章节产物时,再读取文档获取具体内容。
3. 读取智能纪要(`note_doc_token`)内容时,纪要文档的**第一个 `<whiteboard>`** 标签是封面图(AI 生成的总结可视化),应同时下载展示给用户:
```bash
# 1. 读取纪要内容
lark-cli docs +fetch --doc <note_doc_token> --doc-format markdown
# 2. 从返回的 markdown 中提取第一个 <whiteboard token="xxx"/> 的 token
# 3. 下载封面图到聚合目录(和逐字稿、录像同目录,保持产物归拢)
# 并非所有纪要都有封面画板,没有 <whiteboard> 标签时跳过即可
lark-cli docs +media-download --type whiteboard --token <whiteboard_token> --output ./minutes/<minute_token>/cover
```
> **产物目录规范**:同一会议的所有下载产物(录像、逐字稿、封面图等)统一放到 `./minutes/{minute_token}/` 目录下。这与 `minutes +download` 和 `minutes +detail --minute-tokens` 的默认落点保持一致,便于 Agent 聚合。显式路径(如封面图)需手动对齐到同一目录。
> **纪要相关文档 — 根据用户意图选择:**
> - `note_doc_token` → **AI 智能纪要**AI 总结 + 待办),由 `note +detail --note-id <note_id>` 返回
> - `meeting_note` → **用户绑定到日程的会议纪要**,由 [`calendar +meeting --event-ids <event_id>`](../lark-calendar/references/lark-calendar-meeting.md) 返回
> - 用户说"逐字稿""完整记录""谁说了什么"时 → 按 `note_display_type` 路由,详见 [lark-note](../lark-note/SKILL.md)
> - 用户说"纪要""总结""纪要内容"时,应同时返回 `note_doc_token` 和 `meeting_note`(如有)
> - 用户意图不明确时,应展示所有文档链接让用户选择,而不是替用户决定
> - 如果用户提供的是**本地音视频文件**并说"转纪要""转逐字稿",不要直接从 `vc +detail` 开始;应先用 [minutes +upload](../lark-minutes/references/lark-minutes-upload.md) 生成 `minute_url`,再提取 `minute_token` 调用 `minutes +detail --minute-tokens`
### 3. 纪要文档与逐字稿链接
1. 纪要文档、逐字稿文档与关联的共享文档默认使用文档 Token 返回。
2. 仅需要获取文档名称和 URL 等基本信息时,使用 `lark-cli drive metas batch_query` 查询
```bash
# 学习命令使用方式
lark-cli schema drive.metas.batch_query
# 批量获取文档基本信息: 一次最多查询 10 个文档
lark-cli drive metas batch_query --data '{"request_docs": [{"doc_type": "docx", "doc_token": "<doc_token>"}], "with_url": true}'
```
3. 需要获取文档内容时,使用 `lark-cli docs +fetch`
```bash
# 获取文档内容
lark-cli docs +fetch --doc <doc_token> --doc-format markdown
```
### 4. 查询参会人快照(读操作)
用户问"谁参加过这场会议""这个会议有哪些参会人""某某参会了吗"等**参会人快照**类问题时,使用 **`vc meeting get --with-participants`**:这是参会人服务端快照 API,不依赖 bot 身份参会,**已结束会议也可查**:
```bash
lark-cli vc meeting get --params '{"meeting_id":"<meeting_id>","with_participants":true}'
```
选型判断表:
| 用户意图 | 推荐命令 | 所在 skill |
|---------|---------|--------|
| 参会人快照(谁参加过、何时入/离会,任意时点)| `vc meeting get --with-participants` | 本 skill |
| 已结束会议的发言内容 | 优先:`vc +detail``note_id``note +detail``verbatim_doc_token``docs +fetch`;备选:`vc +detail``minute_token``minutes +detail --transcript` | [lark-note](../lark-note/SKILL.md) / [lark-minutes](../lark-minutes/SKILL.md) |
| **进行中会议**的实时事件流(转写、聊天、共享、会中加入/离开)| `vc +meeting-events` | 本 skill / [`lark-vc-agent`](../lark-vc-agent/SKILL.md) |
| **Agent 真实入会 / 离会** | `vc +meeting-join` / `vc +meeting-leave` | [`lark-vc-agent`](../lark-vc-agent/SKILL.md) |
## 资源关系
```text
Meeting (视频会议)
├── Note (会议纪要) ← note_id 标识,note_display_type: normal / unified
│ ├── MainDoc (AI 智能纪要文档, note_doc_token)
│ ├── MeetingNotes (用户绑定的会议纪要文档, meeting_notes)
│ ├── VerbatimDoc (逐字稿, verbatim_doc_token) ← normal 路径
│ ├── UnifiedTranscript (unified 原始记录) ← unified 路径,note +transcriptlark-note
│ └── SharedDoc (会中共享文档)
└── Minutes (妙记) ← minute_token 标识,由 `vc +detail` 或 `vc +recording` 桥接获取,产物详情走 [lark-minutes](../lark-minutes/SKILL.md)
├── Transcript (文字记录)
├── Summary (总结)
├── Todos (待办)
├── Chapters (章节)
└── Keywords (推荐关键词)
```
> **MeetingNotes 边界**:用户绑定到日程的会议纪要文档(`meeting_note`)属于日程域,不在 VC 资源关系内;从 `event_id` 用 [`calendar +meeting`](../lark-calendar/references/lark-calendar-meeting.md) 获取。
>
> **妙记边界**`+recording` 仅负责把 `meeting_id` / `calendar_event_id` 桥接到 `minute_token`;妙记的总结/待办/章节/逐字稿等产物归 [lark-minutes](../lark-minutes/SKILL.md)`minutes +detail`)。
>
> **Note 域边界**VC 域只负责把 `meeting_id` 转成 `note_id` / `minute_token`,纪要详情归 [lark-note](../lark-note/SKILL.md)。
> - 入口选择:从 `meeting_id` 出发用 `vc +detail` 拿 `note_id` 和 `minute_token`;从 `minute_token` 出发用 [`minutes +detail`](../lark-minutes/references/lark-minutes-detail.md) 也会返回关联的 `note_id`,可继续走 `note +detail` 拿纪要文档 token。
> - 已有 `note_id` → 直接走 [`note +detail`](../lark-note/SKILL.md) / [`note +transcript`](../lark-note/SKILL.md),不要绕回 VC。
> - 已有 `doc_token` 且目标是读正文 → [lark-doc](../lark-doc/SKILL.md)。
> - 只有自然语言纪要标题 → 文档搜索 / Docx 正文读取;有显式 `vc-node-id` 才进入 [lark-note](../lark-note/SKILL.md)。
> - 从日程出发(只有 `event_id`)→ 先走 [`calendar +meeting`](../lark-calendar/references/lark-calendar-meeting.md) 拿到 `meeting_id` 或 `meeting_note`,再按上述路径继续。
> - **跨到 lark-minutes / lark-note / lark-doc 时必须沿用来源身份**:例如 `vc +detail --as bot` 拿到的 `note_id`,下一步 `note +detail --note-id <note_id>` 也要显式加 `--as bot`;不要省略 `--as` 让身份被 profile 默认值悄悄换成 user(或反过来)。`note +transcript` 目前仅支持 `--as user`——如果 `note +detail --as bot` 返回 `note_display_type=unified`,停在这一步向用户说明"该纪要的逐字稿只能以 user 身份读取",只有用户明确同意才切到 `--as user`,不要静默切换。
## API Resources
```bash
lark-cli vc <resource> <method> [flags]
```
### meeting
- `get` — 获取会议详情(主题、时间、参会人、note_id)
```bash
# 获取会议基础信息(不含参会人)
lark-cli vc meeting get --params '{"meeting_id": "<meeting_id>"}'
# 获取会议基础信息(含参会人)
lark-cli vc meeting get --params '{"meeting_id": "<meeting_id>", "with_participants": true}'
```
### minutes(跨域,详见 [lark-minutes](../lark-minutes/SKILL.md)
- `get` — 获取妙记基础信息(标题、时长、封面);查询妙记**内容**(总结/待办/章节/逐字稿)请用 [`minutes +detail`](../lark-minutes/references/lark-minutes-detail.md)
## 不在本 skill 范围
- 查询未来的会议日程 → [lark-calendar](../lark-calendar/SKILL.md)
- Agent 真实入会/离会 → [lark-vc-agent](../lark-vc-agent/SKILL.md)
- 只有纪要文档标题的逐字稿查询 → 文档搜索 / Docx 正文读取;有显式 `vc-node-id` 才进入 [lark-note](../lark-note/SKILL.md)
- 本地音视频文件转纪要/逐字稿、妙记搜索/下载/上传/重命名/替换说话人 → [lark-minutes](../lark-minutes/SKILL.md)
- 通过 `note_id` 取纪要文档 Token → [lark-note](../lark-note/SKILL.md)
**MUST 完整读取 [`../lark-meeting/SKILL.md`](../lark-meeting/SKILL.md),并按照其中的路由和行动指南执行。**
@@ -1,49 +0,0 @@
# vc +detail
通过会议 ID 获取会议详情,包括基本信息、关联的纪要 ID(`note_id`)和妙记 Token`minute_token`)。只读,支持 `--as user` / `--as bot`
## 命令
```bash
# 单个 / 批量(逗号分隔,最多 50 个)
lark-cli vc +detail --meeting-ids <meeting_id1>,<meeting_id2>
# bot 身份(只能查 bot 有权限的会议)
lark-cli vc +detail --meeting-ids <meeting_id1>,<meeting_id2> --as bot
```
## 输出字段
| 字段 | 说明 |
|------|------|
| `meeting_id` | 会议 ID |
| `meeting_no` | 会议 9 位号码 |
| `topic` | 会议主题 |
| `start_time` | 开始时间 |
| `end_time` | 结束时间 |
| `note_id` | 关联的纪要 ID。 |
| `minute_token` | 关联的妙记 Token。 |
## 典型场景
### 场景 1:获取会议的纪要和妙记关联
`vc +detail` 只能拿到 `note_id``minute_token`,不直接返回纪要文档 token 与妙记产物内容。要获取实际产物,需根据用户诉求继续调用 `note +detail``minutes +detail`**并沿用第 1 步同一个 `--as`**(完整规则见 [lark-shared](../../lark-shared/SKILL.md) 的「身份延续」):
```bash
# 1. 获取会议详情,拿到 note_id 和 minute_token
lark-cli vc +detail --meeting-ids <meeting_id> --as bot
# 2. 用 note_id 获取纪要文档 Tokennote_doc_token / verbatim_doc_token / shared_doc_tokens
# 显式沿用第 1 步的身份,不要省略 --as
lark-cli note +detail --note-id <note_id> --as bot
# 3. 用 minute_token 获取妙记产物(同样沿用第 1 步的身份)
# ⚠️ 必须显式指定 --summary / --todo / --chapter / --keyword / --transcript 中至少一个 flag
# 不传任何 flag 则不会返回任何产物内容。
lark-cli minutes +detail --minute-tokens obcnxxxxxxxxxxxxxxxxxxxx --todo --transcript --as bot
```
> **路由建议**:当用户未明确指定使用妙记时,**优先**走 `note +detail` 链路(纪要文档信息更完整、含逐字稿原文),仅在 `note_id` 为空或用户要求妙记产物时才走 `minutes +detail`。
> **身份边界**`note +transcript` 目前仅支持 `--as user`。若上面第 2 步用 `--as bot` 拿到 `note_display_type=unified`,停下来向用户说明该纪要逐字稿只能以 user 身份读取,只有用户明确同意才切换身份重试。
@@ -1,203 +0,0 @@
# Calendar/VC/Doc 跨领域关联关系、领域知识和职责边界说明
本文档说明飞书日历(Calendar)、视频会议(VC)、云文档(Doc)三个域之间的关联关系,帮助理解跨域数据流转和产物依赖。
## Calendar 域
- **lark-calendar skill** 负责日历与日程管理,包括创建、查询、修改、删除日程等操作。
- **日程与会议的关系**:日程可以用于提前预约会议,确定会议时间、参与人、会议室、会议主题等信息。日程上可以关联飞书/Lark 视频会议。
- **并非所有会议都通过日程发起**:即时会议不经过日程预约,直接创建。因此,仅查询日程数据无法覆盖所有会议,搜索历史会议应优先使用 `vc +search`
- **日程上的用户会议纪要**:用户可以在日程上绑定自己的会议纪要文档(MeetingNotes),用于手动记录会议相关信息。该文档与 AI 生成的智能纪要(`note_doc_token`)是不同的文档,相互独立。
> **路由规则**:查询过去已结束的会议 → `lark-vc`;查询未来日程/待开的会 → `lark-calendar`;查询"今天有哪些会议" → 两者结合(`vc +search` 查已结束 + `calendar` 查未开始)。
## VC 域
- **lark-vc skill** 负责视频会议管理,包括搜索历史会议、查询会议产物(智能纪要、逐字稿、妙记等)、查询参会人快照等操作。
- **会议类型**:会议可以是日程会议(由日程发起,有对应的 `calendar_event_id`),也可以是即时会议等其他类型。
### 会议产物
会议产物取决于会中开启的功能,分为两条独立链路:
#### 链路一:开启「AI 总结」
会中开启「AI 总结」功能后,产生以下产物:
| 产物 | Token 字段 | 本质 | 说明 |
|------|-----------|------|------|
| 智能纪要 | `note_doc_token` | 飞书文档 | AI 生成的会议总结与待办 |
| 逐字稿 | `verbatim_doc_token` | 飞书文档 | 完整的逐句发言记录(含说话人、时间戳)— **仅 `note_display_type=normal` 时是可读的独立文档**`unified` 纪要的逐字稿用 `note +transcript --note-id <note_id>` 拉取(见下方 [Note 域](#note-域) |
| 共享文档 | `shared_doc_token` | 飞书文档 | 会中投屏共享的文档信息 |
> **授权特性**:智能纪要总结文档及其逐字稿文档(总结文档尾部会挂逐字稿链接与会中投屏共享文档链接)在会后**自动授权给参会人**,参会人通常可直接读取,无需额外申请。
此外,还存在**用户会议纪要(MeetingNotes**,对应 `meeting_note` 字段。这是用户主动绑定到日程的纪要文档,通常用于会前记录会议相关内容,与智能纪要文档相互独立。仅通过 [`calendar +meeting --event-ids`](../../lark-calendar/references/lark-calendar-meeting.md) 路径返回。
#### 链路二:开启「录制」
会中开启「录制」功能后,产生**妙记产物**(`minute_token`)。注意:妙记不一定是会中产生的,用户上传音视频文件或录音也会产生妙记。妙记本身包含以下子产物:
| 子产物 | 说明 |
|--------|------|
| Summary(总结) | 对整场会议的智能总结 |
| Todo(待办) | 会议中识别出的待处理任务列表 |
| Chapter(章节) | 按讨论话题划分的核心内容摘要 |
| Transcript(文字记录) | 整场会议最原始的逐人发言记录 |
> **授权特性**:妙记带有**原始会议录制视频**,会后**不会自动授权给参会人**,需管理员主动授权或参会人主动申请后才能读取(含其 Summary/Todo/Chapter/Transcript 等产物)。因此当同一场会议既有智能纪要又有妙记时,参会人访问**智能纪要及其逐字稿**的门槛通常低于妙记。
#### 两条链路的独立性
- 智能纪要(AI 总结链路)和妙记(录制链路)**相互独立、互不影响**。
- 一场会议可能同时拥有两类产物,也可能只有其中一类,也可能都没有。
- 当两者都存在时,Summary/Todo 内容可能重叠,应根据用户意图选择优先读取哪个。
> **产物选择决策**
> - **AI 产物 vs 原始记录**:智能总结、待办、章节都属于 AI 分析产物,可能只包含最终结论和关键信息。
> - **用户要求"提炼/总结/重新总结/整理/回顾"会议内容时** → **内容总结必须从逐字稿/文字记录出发,基于原始对话独立分析**。禁止直接搬运 AI 纪要的总结作为最终输出——那只是对 AI 产物的重新排版,不是独立提炼。
> - **用户要求查看待办或章节时** → **应参考 AI 产物的待办和章节**,因为 AI 产物的待办更友好(包含提出人和负责人),章节按话题划分更结构化。
> - **用户只想直接看 AI 总结结果** → 使用 AI 产物的总结。
> - **智能纪要 vs 妙记的选择规则**(适用于总结、待办、逐字稿等重复产物,含逐字稿/原始记录):
> - **只存在一类产物** → 用存在的那一类。
> - **两类都存在、用户明确指定了其中一类**(如"看妙记的逐字稿""用妙记总结")→ **语义指向哪个就走哪个链路,不要自作主张改道**。
> - **两类都存在、用户未指定** → **默认用智能纪要及其逐字稿**(智能纪要及逐字稿会后自动授权给参会人,访问门槛更低;妙记含原始录制视频、不自动授权,需申请)。
#### 逐字稿与文字记录的格式
智能纪要的逐字稿(`normal` 纪要的 `verbatim_doc_token` 文档、`unified` 纪要的 `note +transcript` 输出)和妙记的文字记录(Transcript)都记录了用户原始对话内容,格式一致:
```
发言人名称 相对时间戳
<发言内容>
```
示例:
```
张三 00:00:00.195
我们接下来讨论一下项目进度。
```
- 第一行为发言人信息,包含用户名称和发言的相对时间(从会议开始计算的偏移量)。
- 后续行为该发言人的发言内容,直到下一个发言人标记出现。
### 会议总结和分析流程
#### Step 1: 定位会议
根据关键字、组织者、参与人、会议室等条件搜索会议,获取会议列表。
> **不要把纪要标题当会议线索:** 如果用户说“查询 xx 纪要的逐字稿 / 原始记录 / 谁说了什么”,且没有 `meeting_id`、`calendar_event_id`、会议号、参会人或时间范围,先用 `drive +search --query <标题>` 搜索纪要文档,拿到 Docx URL/token 后再 `docs +fetch`。若返回 `<vc-transcribe-tab vc-node-id="...">`,提取 `note_id` 后进入 Note 域判断 `normal` / `unified`;若没有该 block,但有“文字记录/逐字稿” Docx 链接,直接用 `docs +fetch` 读取该链接。
```bash
lark-cli vc +search --start "<YYYY-MM-DD>" --end "<YYYY-MM-DD>" --format json
```
详细用法请阅读 [`lark-vc-search.md`](lark-vc-search.md)。
#### Step 2: 根据 meeting_id 查询产物
> **身份延续**`vc +detail` 支持 `--as user` / `--as bot`。用哪个身份取到 `note_id` / `minute_token`Step 2、Step 3 后续每一条命令(`note +detail`、`minutes +detail`、`docs +fetch`)都要显式带上**同一个** `--as`;不要省略让身份被 profile 默认值悄悄换掉。完整规则见 [`../../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 的「身份延续」。
##### 获取会议产物
当用户提供 `meeting_id` 并需要会议产物时,先用 `vc +detail` 拿到 `note_id``minute_token`
```bash
lark-cli vc +detail --meeting-ids '<meeting_id1>,<meeting_id2>'
```
详细用法请阅读 [`lark-vc-detail.md`](lark-vc-detail.md)。
**优先路径:通过 `note_id` 获取纪要产物**
如果用户未明确要求使用妙记,且返回了 `note_id`**优先**使用 `note +detail` 获取纪要文档的 token 信息(沿用上一步的 `--as`):
```bash
lark-cli note +detail --note-id <note_id>
```
可获取会议的所有产物信息,包括:
- 纪要标识(`note_id`)与展示类型(`note_display_type``unknown` / `normal` / `unified`)— 决定逐字稿走哪条路由
- 智能纪要(`note_doc_token`)— AI 生成的总结和待办信息
- 逐字稿(`verbatim_doc_token`)— 完整的会中发言记录(仅 `normal` 纪要可直接读取该文档)
- 共享文档(`shared_doc_token`)— 会中投屏共享的文档
拿到文档 token 后,再通过 Doc 域 `docs +fetch` 拉取文档正文内容(见 Step 3)。详细用法请阅读 [`lark-note-detail.md`](../../lark-note/references/lark-note-detail.md)。
**备选路径:通过 `minute_token` 获取妙记产物**
如果 `note_id` 为空,或用户明确要求使用妙记产物,则使用 `minutes +detail` 获取妙记的具体产物:
```bash
# 必须显式指定要获取的产物 flag,至少传一个;不传则不会返回任何产物内容
lark-cli minutes +detail --minute-tokens '<minute_token1>,<minute_token2>' \
--summary --todo --chapter --keyword --transcript
```
> **注意**`minutes +detail` 需要**手动指定**要获取的产物 flag,可选 `--summary`(总结)、`--todo`(待办)、`--chapter`(章节)、`--keyword`(关键词)、`--transcript`(文字记录)。**未传任何产物 flag 时不会返回产物内容**,请按用户诉求按需指定。详细用法请阅读 [`lark-minutes-detail.md`](../../lark-minutes/references/lark-minutes-detail.md)。
#### Step 3: 按 `note_display_type` 拉取正文 / 逐字稿
智能纪要(`note_doc_token`)是飞书文档,使用 `docs +fetch` 读取正文内容;**逐字稿的读取方式由 `note_display_type` 决定**
读正文是本链路的最后一跳,身份仍由本链路决定:`--as <user|bot>` 一律填 Step 2 取得 token 时用的那个身份。[lark-doc](../../lark-doc/SKILL.md) 对普通文档推荐 `--as user`,那是用户自有文档的默认建议,**不适用于这里的纪要文档 token**,不要因此切回 user。
```bash
# 纪要正文(两种展示类型都适用)
lark-cli docs +fetch --doc <note_doc_token> --doc-format markdown
# note_display_type=normal:逐字稿是独立文档
lark-cli docs +fetch --doc <verbatim_doc_token> --doc-format markdown
# note_display_type=unified:逐字稿不是独立文档,按 note_id 拉取
# ⚠️ note +transcript 目前仅支持 --as user;如果上面的 note_id 是通过 --as bot
# 拿到的,在这一步停下来向用户说明"该纪要逐字稿只能以 user 身份读取",
# 只有用户明确同意才切到 --as user,不要静默切换身份重试
lark-cli note +transcript --note-id <note_id>
```
详细用法请参考 [lark-doc](../../lark-doc/SKILL.md) 与 [lark-note](../../lark-note/SKILL.md) skill。
#### Step 4: 判断用户需要的产物内容
- 根据用户诉求(总结/待办/章节/完整发言记录等),选择合适的产物进行分析和信息提取
- 如果两种产物都不存在或没有权限,需如实告知用户
## Note 域
- VC 只负责从 `meeting_id` 定位会议产物和 `note_id` / `minute_token`[`vc +detail`](lark-vc-detail.md))。
- 已知 `note_id` 后切到 [lark-note](../../lark-note/SKILL.md);逐字稿路由以 `lark-note``note_display_type` 规则为准。
- 已知 `minute_token` 时,[`minutes +detail`](../../lark-minutes/references/lark-minutes-detail.md) 顶层会一并返回该妙记关联的 `note_id`(如有);可直接传给 `note +detail` 取纪要文档 token,无需绕回 VC。
- 仅有日程 `event_id` 时,先走 [`calendar +meeting`](../../lark-calendar/references/lark-calendar-meeting.md) 拿到 `meeting_id` 或用户绑定的 `meeting_note`,再按上述路径继续。
- 只有自然语言纪要标题时,先走文档搜索与 `docs +fetch`;只有 `<vc-transcribe-tab vc-node-id="...">``vc-node-id` 可以进入 Note 域。
- `doc_token` / Docx URL 不是 `note_id`。没有 `vc-node-id` 时不要反推 Note,继续按 Doc 域读取正文或正文中明确给出的逐字稿文档。
## Doc 域
- **lark-doc skill** 负责飞书云文档管理,包括获取文档元信息、读取文档内容、创建和编辑文档等操作。
- **会议产物的文档本质**:智能纪要(`note_doc_token`)和 `normal` 纪要的逐字稿(`verbatim_doc_token`)都是飞书文档,需要通过 `lark-doc` 的 API(如 `docs +fetch`)查询其内容和元信息;`unified` 纪要的逐字稿不是独立文档,用 `note +transcript` 拉取([lark-note](../../lark-note/SKILL.md))。
- **文档元信息查询**:获取文档名称、URL 等基本信息时,使用 `drive metas batch_query`;获取文档正文内容时,使用 `docs +fetch`
## 三域关联总览
```
Calendar (日程) ──── 发起预约 ────► VC (会议)
┌──────────────────┤
│ │
AI 总结链路 录制链路
│ │
▼ ▼
智能纪要 (Doc) 妙记 (Minutes)
逐字稿 (Doc) ├── Summary
共享文档 (Doc) ├── Todo
用户纪要 (Doc) ├── Chapter
└── Transcript
```
- Calendar 提供会议预约入口,但并非所有会议都来自日程。
- VC 是会议数据的中心,管理会议记录和产物关联。
- Doc 是会议产物的载体,智能纪要和逐字稿都以飞书文档形式沉淀,需通过 Doc 域 API 读取。
+10 -14
View File
@@ -5,17 +5,12 @@ description: "会议纪要整理工作流:汇总指定时间范围内的会议
metadata:
requires:
bins: ["lark-cli"]
skills: ["lark-meeting"]
---
# 会议纪要汇总工作流
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md),其中包含认证、权限处理**。然后阅读 [`../lark-vc/SKILL.md`](../lark-vc/SKILL.md),了解会议纪要相关操作
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../lark-vc/references/vc-domain-boundaries.md`](../lark-vc/references/vc-domain-boundaries.md)**,不读将导致命令使用、会议产物决策、领域边界职责判断错误:
> 1. 了解日历 & VC、会议产物 & 文档的关联关系和职责划分
> 2. 了解会议产物(妙记和纪要)之间的关联关系,例如:**妙记和纪要产生条件相互独立**
> 3. 了解不同会议产物的组成部分,以便根据需求决策使用哪种产物的数据
> 4. 了解会议总结、分析和信息提取的标准流程
**CRITICAL — 开始前 MUST 先完整读取 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md) [`../lark-meeting/SKILL.md`](../lark-meeting/SKILL.md)**。认证、身份和权限以 lark-shared 为准;会议与产物关系、产物选择和逐字稿路由以 lark-meeting 为准
## 适用场景
@@ -91,11 +86,11 @@ lark-cli note +detail --note-id "note_id"
> lark-cli minutes +detail --minute-tokens "<minute_token>" --transcript --output-dir ./transcripts --as user
> ```
>
> 逐字稿会落盘,供 Step 4 基于原始发言独立提炼(不要照搬 AI 总结)。若返回 `No read permission``2091005`),先把无权限事实告知用户,用户明确同意后再用单数 flag 申请:`lark-cli minutes +apply-permission --minute-token "<minute_token>" --perm view --as user`;申请需 owner 在客户端批准后才可重试。详见 [lark-minutes](../lark-minutes/SKILL.md)。
> 逐字稿会落盘,供 Step 4 基于原始发言独立提炼(不要照搬 AI 总结)。若返回 `No read permission``2091005`),先把无权限事实告知用户,用户明确同意后再用单数 flag 申请:`lark-cli minutes +apply-permission --minute-token "<minute_token>" --perm view --as user`;申请需 owner 在客户端批准后才可重试。详见 [基于 minute_token 查询妙记及关联产物](../lark-meeting/scenes/query-minutes-and-artifacts.md)。
> **逐字稿路由按 `note_display_type` 决定**(详见 [vc-domain-boundaries.md](../lark-vc/references/vc-domain-boundaries.md) 的 Note 域):
> **逐字稿路由按 `note_display_type` 决定**(详见 [基于 note_id 查询智能纪要及关联产物](../lark-meeting/scenes/query-note-and-artifacts.md)):
> - `normal`:逐字稿是独立文档,链接/正文走 `verbatim_doc_token`。
> - `unified`:逐字稿**不是独立文档**,没有可分享的逐字稿文档链接;需要逐字稿内容时用 `note +transcript --note-id <note_id>`[lark-note](../lark-note/SKILL.md))拉取到本地,报告中标注"unified 纪要"即可。
> - `unified`:逐字稿**不是独立文档**,没有可分享的逐字稿文档链接;需要逐字稿内容时用 `note +transcript --note-id <note_id>`[lark-meeting](../lark-meeting/SKILL.md))拉取到本地,报告中标注"unified 纪要"即可。
2. 获取纪要文档和逐字稿文档链接
```bash
@@ -127,7 +122,8 @@ lark-cli docs +update --doc "<url_or_token>" --command append --doc-format markd
## 参考
- [lark-shared](../lark-shared/SKILL.md) — 认证、权限(必读)
- [lark-vc](../lark-vc/SKILL.md) — `+search``+detail` 详细用法
- [lark-note](../lark-note/SKILL.md) — `note +detail``note +transcript`unified 纪要逐字稿)
- [lark-minutes](../lark-minutes/SKILL.md) — `minutes +detail``+apply-permission``note_id` 时的妙记备选路径
- [lark-doc](../lark-doc/SKILL.md) — `+fetch``+create``+update` 详细用法
- [lark-meeting](../lark-meeting/SKILL.md) — 会议与产物统一路由
- [查询会议与会议产物](../lark-meeting/scenes/query-meeting-and-artifacts.md) — 搜索、消歧、产物获取与逐字稿分析流程
- [查询妙记及关联产物](../lark-meeting/scenes/query-minutes-and-artifacts.md) — `note_id` 时的妙记备选路径
- [`vc +search`](../lark-meeting/references/lark-vc-search.md)、[`vc +detail`](../lark-meeting/references/lark-vc-detail.md)、[`note +detail`](../lark-meeting/references/lark-note-detail.md)、[`note +transcript`](../lark-meeting/references/lark-note-transcript.md)、[`minutes +detail`](../lark-meeting/references/lark-minutes-detail.md)、[`minutes +apply-permission`](../lark-meeting/references/lark-minutes-apply-permission.md) — 命令细节
- [lark-doc](../lark-doc/SKILL.md) — `+fetch``+create``+update` 详细用法
@@ -0,0 +1,72 @@
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package vc
import (
"bytes"
"context"
"os/exec"
"path/filepath"
"strings"
"testing"
"time"
)
func TestMeetingSkillIsEmbeddedInBuiltCLI(t *testing.T) {
repoRoot := vcContractPath(t)
bin := filepath.Join(t.TempDir(), "lark-cli")
buildCtx, cancelBuild := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancelBuild()
build := exec.CommandContext(buildCtx, "go", "build", "-o", bin, ".")
build.Dir = repoRoot
if output, err := build.CombinedOutput(); err != nil {
t.Fatalf("build lark-cli: %v\n%s", err, output)
}
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
t.Setenv("LARKSUITE_CLI_REMOTE_META", "off")
t.Setenv("LARKSUITE_CLI_NO_UPDATE_NOTIFIER", "1")
t.Setenv("LARKSUITE_CLI_NO_SKILLS_NOTIFIER", "1")
tests := []struct {
name string
args []string
want string
}{
{
name: "main skill",
args: []string{"skills", "read", "lark-meeting"},
want: "name: lark-meeting",
},
{
name: "scene",
args: []string{"skills", "read", "lark-meeting", "scenes/query-meeting-and-artifacts.md"},
want: "# 查询会议及其产物",
},
{
name: "reference",
args: []string{"skills", "read", "lark-meeting", "references/lark-vc-detail.md"},
want: "# vc +detail",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, bin, tt.args...)
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
t.Fatalf("lark-cli %v: %v\nstdout:\n%s\nstderr:\n%s", tt.args, err, stdout.String(), stderr.String())
}
if !strings.Contains(stdout.String(), tt.want) {
t.Fatalf("lark-cli %v output missing %q:\n%s", tt.args, tt.want, stdout.String())
}
})
}
}
@@ -15,14 +15,19 @@ import (
"github.com/stretchr/testify/require"
)
func TestVCMeetingReferencesAreSharedByBothSkills(t *testing.T) {
vcSkill := readVCContractFile(t, "skills", "lark-vc", "SKILL.md")
agentSkill := readVCContractFile(t, "skills", "lark-vc-agent", "SKILL.md")
func TestLegacyVCSkillsRouteToMeetingSkill(t *testing.T) {
for _, skillName := range []string{"lark-vc", "lark-vc-agent"} {
t.Run(skillName, func(t *testing.T) {
skill := readVCContractFile(t, "skills", skillName, "SKILL.md")
require.Contains(t, skill, "本技能只用于兼容旧名称,不直接处理业务。")
require.Contains(t, skill, "../lark-meeting/SKILL.md")
require.Contains(t, skill, `skills: ["lark-meeting"]`)
})
}
}
require.Contains(t, vcSkill, "查询进行中的会议、会中事件或发送会中消息")
require.Contains(t, agentSkill, `"会议现在还开着,谁刚加入了"`)
require.Contains(t, agentSkill, `"会议里谁在发言"`)
require.Contains(t, agentSkill, `"我/某个用户现在在哪个会里"`)
func TestMeetingSkillOwnsVCReferences(t *testing.T) {
meetingSkill := readVCContractFile(t, "skills", "lark-meeting", "SKILL.md")
references := []struct {
sharedName string
@@ -48,17 +53,21 @@ func TestVCMeetingReferencesAreSharedByBothSkills(t *testing.T) {
for _, reference := range references {
t.Run(reference.sharedName, func(t *testing.T) {
require.Contains(t, vcSkill, "references/"+reference.sharedName)
require.Contains(t, agentSkill, "../lark-vc/references/"+reference.sharedName)
require.Contains(t, meetingSkill, "references/"+reference.sharedName)
content := readVCContractFile(t, "skills", "lark-vc", "references", reference.sharedName)
content := readVCContractFile(t, "skills", "lark-meeting", "references", reference.sharedName)
require.Contains(t, content, reference.command)
require.Contains(t, content, "--as user")
require.Contains(t, content, "--as bot")
oldPath := vcContractPath(t, "skills", "lark-vc-agent", "references", reference.oldName)
_, err := vfs.Stat(oldPath)
require.True(t, errors.Is(err, fs.ErrNotExist), "legacy reference still exists: %s", oldPath)
oldPaths := []string{
vcContractPath(t, "skills", "lark-vc", "references", reference.sharedName),
vcContractPath(t, "skills", "lark-vc-agent", "references", reference.oldName),
}
for _, oldPath := range oldPaths {
_, err := vfs.Stat(oldPath)
require.True(t, errors.Is(err, fs.ErrNotExist), "legacy reference still exists: %s", oldPath)
}
})
}
}
@@ -73,8 +82,8 @@ func TestVCSharedMeetingReferencesHaveValidMarkdownLinks(t *testing.T) {
for _, reference := range references {
t.Run(reference, func(t *testing.T) {
path := vcContractPath(t, "skills", "lark-vc", "references", reference)
content := readVCContractFile(t, "skills", "lark-vc", "references", reference)
path := vcContractPath(t, "skills", "lark-meeting", "references", reference)
content := readVCContractFile(t, "skills", "lark-meeting", "references", reference)
links := linkPattern.FindAllStringSubmatch(content, -1)
require.NotEmpty(t, links, "expected local markdown links in %s", path)