Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions shortcuts/minutes/minutes_speaker_replace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,27 @@ func TestMinutesSpeakerReplace_Validate(t *testing.T) {
},
{
name: "missing from",
args: []string{"+speaker-replace", "--minute-token", "obcn123456", "--to-user-id", "ou_b", "--as", "user"},
args: []string{"+speaker-replace", "--minute-token", minutesSpeakerReplaceTestToken, "--to-user-id", "ou_b", "--as", "user"},
wantErr: "required flag(s) \"from-user-id\" not set",
},
{
name: "missing to",
args: []string{"+speaker-replace", "--minute-token", "obcn123456", "--from-user-id", "ou_a", "--as", "user"},
args: []string{"+speaker-replace", "--minute-token", minutesSpeakerReplaceTestToken, "--from-user-id", "ou_a", "--as", "user"},
wantErr: "required flag(s) \"to-user-id\" not set",
},
{
name: "invalid from prefix",
args: []string{"+speaker-replace", "--minute-token", "obcn123456", "--from-user-id", "u_a", "--to-user-id", "ou_b", "--as", "user"},
args: []string{"+speaker-replace", "--minute-token", minutesSpeakerReplaceTestToken, "--from-user-id", "u_a", "--to-user-id", "ou_b", "--as", "user"},
wantErr: "invalid user ID format",
},
{
name: "invalid to prefix",
args: []string{"+speaker-replace", "--minute-token", "obcn123456", "--from-user-id", "ou_a", "--to-user-id", "u_b", "--as", "user"},
args: []string{"+speaker-replace", "--minute-token", minutesSpeakerReplaceTestToken, "--from-user-id", "ou_a", "--to-user-id", "u_b", "--as", "user"},
wantErr: "invalid user ID format",
},
{
name: "from equals to",
args: []string{"+speaker-replace", "--minute-token", "obcn123456", "--from-user-id", "ou_same", "--to-user-id", "ou_same", "--as", "user"},
args: []string{"+speaker-replace", "--minute-token", minutesSpeakerReplaceTestToken, "--from-user-id", "ou_same", "--to-user-id", "ou_same", "--as", "user"},
wantErr: "must be different",
},
}
Expand Down Expand Up @@ -87,12 +87,12 @@ func TestMinutesSpeakerReplace_ValidateTyped(t *testing.T) {
}{
{
name: "invalid from prefix",
args: []string{"+speaker-replace", "--minute-token", "obcn123456", "--from-user-id", "u_a", "--to-user-id", "ou_b", "--as", "user"},
args: []string{"+speaker-replace", "--minute-token", minutesSpeakerReplaceTestToken, "--from-user-id", "u_a", "--to-user-id", "ou_b", "--as", "user"},
wantParam: "--from-user-id",
},
{
name: "from equals to",
args: []string{"+speaker-replace", "--minute-token", "obcn123456", "--from-user-id", "ou_same", "--to-user-id", "ou_same", "--as", "user"},
args: []string{"+speaker-replace", "--minute-token", minutesSpeakerReplaceTestToken, "--from-user-id", "ou_same", "--to-user-id", "ou_same", "--as", "user"},
wantParam: "--to-user-id",
},
}
Expand Down
73 changes: 73 additions & 0 deletions shortcuts/minutes/minutes_summary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT

package minutes

import (
"context"
"fmt"
"net/http"
"strings"

"github.com/larksuite/cli/errs"
"github.com/larksuite/cli/internal/validate"
"github.com/larksuite/cli/shortcuts/common"
)

const minutesSummaryMarkdownTip = "Summary accepts any text; unsupported Markdown is saved but may display as literal raw text in Minutes. For best rendering, prefer plain text, line breaks, headings (#, ##, ###), bold (**text**), and lists (-, *, or 1.)."

// MinutesSummary replaces the AI summary of a minute.
var MinutesSummary = common.Shortcut{
Service: "minutes",
Command: "+summary",
Description: "Replace the AI summary of a minute",
Risk: "write",
Scopes: []string{"minutes:minutes:update"},
AuthTypes: []string{"user"},
HasFormat: true,
Flags: []common.Flag{
{Name: "minute-token", Desc: "minute token", Required: true},
{Name: "summary", Desc: "replacement summary text (Markdown subset renders best in Minutes)", Required: true, Input: []string{common.File, common.Stdin}},
},
Tips: []string{
minutesSummaryMarkdownTip,
"Use `lark-cli vc +notes --minute-tokens <token>` to read the current summary before replacing it.",
},
Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
minuteToken := runtime.Str("minute-token")
if minuteToken == "" {
return errs.NewValidationError(errs.SubtypeInvalidArgument, "--minute-token is required").WithParam("--minute-token")

Check warning on line 39 in shortcuts/minutes/minutes_summary.go

View check run for this annotation

Codecov / codecov/patch

shortcuts/minutes/minutes_summary.go#L39

Added line #L39 was not covered by tests
}
if err := validate.ResourceName(minuteToken, "--minute-token"); err != nil {
return errs.NewValidationError(errs.SubtypeInvalidArgument, "%s", err).WithParam("--minute-token")

Check warning on line 42 in shortcuts/minutes/minutes_summary.go

View check run for this annotation

Codecov / codecov/patch

shortcuts/minutes/minutes_summary.go#L42

Added line #L42 was not covered by tests
}
summary := strings.TrimSpace(runtime.Str("summary"))
if summary == "" {
return errs.NewValidationError(errs.SubtypeInvalidArgument, "--summary is required").WithParam("--summary")

Check warning on line 46 in shortcuts/minutes/minutes_summary.go

View check run for this annotation

Codecov / codecov/patch

shortcuts/minutes/minutes_summary.go#L46

Added line #L46 was not covered by tests
}
return nil
},
Comment thread
zhangjun-bytedance marked this conversation as resolved.
DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
return common.NewDryRunAPI().
PUT(fmt.Sprintf("/open-apis/minutes/v1/minutes/%s/summary", validate.EncodePathSegment(runtime.Str("minute-token")))).
Body(map[string]interface{}{"summary": "<summary markdown>"})
},
Execute: func(ctx context.Context, runtime *common.RuntimeContext) error {
minuteToken := runtime.Str("minute-token")
summary := strings.TrimSpace(runtime.Str("summary"))

Check warning on line 57 in shortcuts/minutes/minutes_summary.go

View check run for this annotation

Codecov / codecov/patch

shortcuts/minutes/minutes_summary.go#L55-L57

Added lines #L55 - L57 were not covered by tests

path := fmt.Sprintf("/open-apis/minutes/v1/minutes/%s/summary", validate.EncodePathSegment(minuteToken))
body := map[string]interface{}{
"summary": summary,

Check warning on line 61 in shortcuts/minutes/minutes_summary.go

View check run for this annotation

Codecov / codecov/patch

shortcuts/minutes/minutes_summary.go#L59-L61

Added lines #L59 - L61 were not covered by tests
}
if _, err := runtime.CallAPITyped(http.MethodPut, path, nil, body); err != nil {
return err

Check warning on line 64 in shortcuts/minutes/minutes_summary.go

View check run for this annotation

Codecov / codecov/patch

shortcuts/minutes/minutes_summary.go#L63-L64

Added lines #L63 - L64 were not covered by tests
}

runtime.OutFormat(map[string]interface{}{
"minute_token": minuteToken,
"updated": true,
}, nil, nil)
return nil

Check warning on line 71 in shortcuts/minutes/minutes_summary.go

View check run for this annotation

Codecov / codecov/patch

shortcuts/minutes/minutes_summary.go#L67-L71

Added lines #L67 - L71 were not covered by tests
},
}
Loading
Loading