mirror of
https://github.com/larksuite/cli.git
synced 2026-07-06 16:18:05 +08:00
Compare commits
1 Commits
feat/sidec
...
feat/minut
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7feefa8b4 |
@@ -41,7 +41,6 @@ var (
|
||||
scopesMinuteTokens = []string{
|
||||
"minutes:minutes:readonly",
|
||||
"minutes:minutes.artifacts:read",
|
||||
"minutes:minutes.transcript:export",
|
||||
}
|
||||
scopesCalendarEventIDs = []string{
|
||||
"calendar:calendar:read",
|
||||
@@ -359,15 +358,10 @@ func downloadTranscriptFile(runtime *common.RuntimeContext, minuteToken string,
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(errOut, "%s downloading transcript: %s\n", logPrefix, transcriptPath)
|
||||
fmt.Fprintf(errOut, "%s writing transcript file: %s\n", logPrefix, transcriptPath)
|
||||
apiResp, err := runtime.DoAPI(&larkcore.ApiReq{
|
||||
HttpMethod: http.MethodGet,
|
||||
ApiPath: fmt.Sprintf("/open-apis/minutes/v1/minutes/%s/transcript", validate.EncodePathSegment(minuteToken)),
|
||||
QueryParams: larkcore.QueryParams{
|
||||
"need_speaker": []string{"true"},
|
||||
"need_timestamp": []string{"true"},
|
||||
"file_format": []string{"txt"},
|
||||
},
|
||||
ApiPath: fmt.Sprintf("/open-apis/minutes/v1/minutes/%s/artifacts", validate.EncodePathSegment(minuteToken)),
|
||||
}, larkcore.WithFileDownload())
|
||||
if err != nil {
|
||||
fmt.Fprintf(errOut, "%s failed to download transcript: %v\n", logPrefix, err)
|
||||
@@ -570,9 +564,8 @@ var VCNotes = common.Shortcut{
|
||||
GET("/open-apis/minutes/v1/minutes/{minute_token}").
|
||||
GET("/open-apis/vc/v1/notes/{note_id}").
|
||||
GET("/open-apis/minutes/v1/minutes/{minute_token}/artifacts").
|
||||
GET("/open-apis/minutes/v1/minutes/{minute_token}/transcript").
|
||||
Set("minute_tokens", common.SplitCSV(tokens)).
|
||||
Set("steps", "minutes API → note detail + AI artifacts + transcript")
|
||||
Set("steps", "minutes API → note detail + AI artifacts (also streamed to transcript.txt)")
|
||||
}
|
||||
ids := runtime.Str("calendar-event-ids")
|
||||
return common.NewDryRunAPI().
|
||||
|
||||
@@ -131,32 +131,6 @@ func artifactsStub(token string) *httpmock.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
func emptyArtifactsStub(token string) *httpmock.Stub {
|
||||
return &httpmock.Stub{
|
||||
Method: "GET",
|
||||
URL: "/open-apis/minutes/v1/minutes/" + token + "/artifacts",
|
||||
Body: map[string]interface{}{"code": 0, "msg": "ok", "data": map[string]interface{}{}},
|
||||
}
|
||||
}
|
||||
|
||||
func transcriptStub(token string) *httpmock.Stub {
|
||||
return &httpmock.Stub{
|
||||
Method: "GET",
|
||||
URL: "/open-apis/minutes/v1/minutes/" + token + "/transcript",
|
||||
Body: map[string]interface{}{"code": 0, "msg": "ok", "data": map[string]interface{}{}},
|
||||
}
|
||||
}
|
||||
|
||||
// transcriptRawStub returns an actual transcript body so downloadTranscriptFile
|
||||
// writes a file to disk. Used by path-layout tests.
|
||||
func transcriptRawStub(token string, body []byte) *httpmock.Stub {
|
||||
return &httpmock.Stub{
|
||||
Method: "GET",
|
||||
URL: "/open-apis/minutes/v1/minutes/" + token + "/transcript",
|
||||
RawBody: body,
|
||||
}
|
||||
}
|
||||
|
||||
func minuteGetStub(token, noteID, title string) *httpmock.Stub {
|
||||
minute := map[string]interface{}{"title": title}
|
||||
if noteID != "" {
|
||||
@@ -671,13 +645,19 @@ func chdirForTest(t *testing.T) string {
|
||||
return dir
|
||||
}
|
||||
|
||||
// TestNotes_TranscriptDefaultLayout verifies the file-layout contract: with no
|
||||
// --output-dir flag, the transcript file lands at ./minutes/{minute_token}/transcript.txt.
|
||||
// The transcript file is sourced from GetMinuteArtifacts (HTTP path
|
||||
// /v1/minutes/:minute_token/artifacts) — the same endpoint also feeds inline
|
||||
// AI artifact parsing, so the stub is marked Reusable to satisfy both calls.
|
||||
func TestNotes_TranscriptDefaultLayout(t *testing.T) {
|
||||
chdirForTest(t)
|
||||
|
||||
f, stdout, _, reg := cmdutil.TestFactory(t, defaultConfig())
|
||||
reg.Register(minuteGetStub("tok001", "", "Meeting Title"))
|
||||
reg.Register(emptyArtifactsStub("tok001"))
|
||||
reg.Register(transcriptRawStub("tok001", []byte("speaker1: hello world\n")))
|
||||
artStub := artifactsStub("tok001")
|
||||
artStub.Reusable = true
|
||||
reg.Register(artStub)
|
||||
|
||||
err := mountAndRun(t, VCNotes, []string{
|
||||
"+notes", "--minute-tokens", "tok001", "--as", "user",
|
||||
@@ -687,12 +667,12 @@ func TestNotes_TranscriptDefaultLayout(t *testing.T) {
|
||||
}
|
||||
|
||||
wantPath := "minutes/tok001/transcript.txt"
|
||||
data, err := os.ReadFile(wantPath)
|
||||
info, err := os.Stat(wantPath)
|
||||
if err != nil {
|
||||
t.Fatalf("expected file at %s: %v", wantPath, err)
|
||||
}
|
||||
if string(data) != "speaker1: hello world\n" {
|
||||
t.Errorf("content mismatch: %q", string(data))
|
||||
if info.Size() == 0 {
|
||||
t.Errorf("expected non-empty transcript file streamed from artifacts response, got 0 bytes")
|
||||
}
|
||||
|
||||
if _, err := os.Stat("artifact-Meeting Title-tok001"); err == nil {
|
||||
@@ -705,8 +685,9 @@ func TestNotes_TranscriptExplicitOutputDir_PreservesLegacyLayout(t *testing.T) {
|
||||
|
||||
f, _, _, reg := cmdutil.TestFactory(t, defaultConfig())
|
||||
reg.Register(minuteGetStub("tok001", "", "Meeting Title"))
|
||||
reg.Register(emptyArtifactsStub("tok001"))
|
||||
reg.Register(transcriptRawStub("tok001", []byte("content")))
|
||||
artStub := artifactsStub("tok001")
|
||||
artStub.Reusable = true
|
||||
reg.Register(artStub)
|
||||
|
||||
if err := os.MkdirAll("out", 0755); err != nil {
|
||||
t.Fatalf("setup: %v", err)
|
||||
|
||||
@@ -158,7 +158,7 @@ lark-cli vc meeting get --params '{"meeting_id": "<meeting_id>", "with_participa
|
||||
| 方法 | 所需 scope |
|
||||
|------|-----------|
|
||||
| `+notes --meeting-ids` | `vc:meeting.meetingevent:read`、`vc:note:read` |
|
||||
| `+notes --minute-tokens` | `vc:note:read`、`minutes:minutes:readonly`、`minutes:minutes.artifacts:read`、`minutes:minutes.transcript:export` |
|
||||
| `+notes --minute-tokens` | `vc:note:read`、`minutes:minutes:readonly`、`minutes:minutes.artifacts:read` |
|
||||
| `+notes --calendar-event-ids` | `calendar:calendar:read`、`calendar:calendar.event:read`、`vc:meeting.meetingevent:read`、`vc:note:read` |
|
||||
| `+recording --meeting-ids` | `vc:record:readonly` |
|
||||
| `+recording --calendar-event-ids` | `vc:record:readonly`、`calendar:calendar:read`、`calendar:calendar.event:read` |
|
||||
|
||||
@@ -64,7 +64,7 @@ lark-cli vc +notes --meeting-ids 69xxxxxxxxxxxxx28 --dry-run
|
||||
| 输入 | 所需权限 |
|
||||
|------|---------|
|
||||
| `--meeting-ids` | `vc:meeting.meetingevent:read`、`vc:note:read` |
|
||||
| `--minute-tokens` | `vc:note:read`、`minutes:minutes:readonly`、`minutes:minutes.artifacts:read`、`minutes:minutes.transcript:export` |
|
||||
| `--minute-tokens` | `vc:note:read`、`minutes:minutes:readonly`、`minutes:minutes.artifacts:read` |
|
||||
| `--calendar-event-ids` | `calendar:calendar:read`、`calendar:calendar.event:read`、`vc:meeting.meetingevent:read`、`vc:note:read` |
|
||||
|
||||
## 输出结果
|
||||
|
||||
Reference in New Issue
Block a user