Documentation
¶
Overview ¶
Package note owns the Note domain: querying note detail and the unified transcript by a known note_id. The vc domain locates a note_id from meeting context and delegates note-detail parsing here, so the parsing logic lives in exactly one place.
Index ¶
Constants ¶
const NoNoteReadPermissionCode = 121005
NoNoteReadPermissionCode is returned when the caller lacks read permission for the requested note.
Variables ¶
var ErrEmptyDetail = errors.New("note detail is empty")
ErrEmptyDetail identifies note detail responses that do not contain a note object. Callers should use errors.Is instead of matching the display message.
var NoteDetail = common.Shortcut{ Service: "note", Command: "+detail", Description: "Get note detail (display type, document tokens) by note_id", Risk: "read", Scopes: []string{"vc:note:read"}, AuthTypes: []string{"user"}, Flags: []common.Flag{ {Name: "note-id", Desc: "note ID", Required: true}, }, Validate: func(_ context.Context, runtime *common.RuntimeContext) error { noteID := strings.TrimSpace(runtime.Str("note-id")) if noteID == "" { return errs.NewValidationError(errs.SubtypeInvalidArgument, "--note-id is required").WithParam("--note-id") } if err := validate.ResourceName(noteID, "--note-id"); err != nil { return errs.NewValidationError(errs.SubtypeInvalidArgument, "%s", err).WithParam("--note-id").WithCause(err) } return nil }, DryRun: func(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { noteID := strings.TrimSpace(runtime.Str("note-id")) return common.NewDryRunAPI(). GET(fmt.Sprintf("/open-apis/vc/v1/notes/%s", validate.EncodePathSegment(noteID))) }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { noteID := strings.TrimSpace(runtime.Str("note-id")) detail, err := FetchDetail(ctx, runtime, noteID) if err != nil { return mapNoteError(err) } runtime.OutFormat(map[string]any{"note": detail.ToMap()}, nil, nil) return nil }, }
NoteDetail queries note metadata, display type and document tokens by note_id.
var NoteTranscript = common.Shortcut{ Service: "note", Command: "+transcript", Description: "Fetch the unified note transcript and save it to a file", Risk: "read", Scopes: []string{"vc:note:read"}, AuthTypes: []string{"user"}, Flags: []common.Flag{ {Name: "note-id", Desc: "note ID", Required: true}, {Name: "transcript-format", Desc: "transcript content format", Default: transcriptFormatMarkdown, Enum: []string{transcriptFormatMarkdown, transcriptFormatPlainText}}, {Name: "locale", Desc: "transcript locale, e.g. zh_cn, en_us, ja_jp (default follows profile language or brand)"}, {Name: "output", Desc: "output file path (default: ./notes/{note_id}/unified_transcript.{md,txt})"}, {Name: "overwrite", Type: "bool", Desc: "overwrite an existing output file"}, }, Validate: func(_ context.Context, runtime *common.RuntimeContext) error { noteID := strings.TrimSpace(runtime.Str("note-id")) if noteID == "" { return errs.NewValidationError(errs.SubtypeInvalidArgument, "--note-id is required").WithParam("--note-id") } if err := validate.ResourceName(noteID, "--note-id"); err != nil { return errs.NewValidationError(errs.SubtypeInvalidArgument, "%s", err).WithParam("--note-id").WithCause(err) } if out := strings.TrimSpace(runtime.Str("output")); out != "" { if err := common.ValidateSafePathTyped(runtime.FileIO(), out); err != nil { return err } } return nil }, DryRun: func(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { noteID := strings.TrimSpace(runtime.Str("note-id")) transcriptFormat := runtime.Str("transcript-format") locale := resolveTranscriptLocale(runtime) return common.NewDryRunAPI(). GET(fmt.Sprintf("/open-apis/vc/v1/notes/%s", validate.EncodePathSegment(noteID))). Desc("[1] Check note_display_type and verbatim_doc_token before transcript fetch"). GET(fmt.Sprintf("/open-apis/vc/v1/notes/%s/unified_note_transcript", validate.EncodePathSegment(noteID))). Desc("[2] Fetch unified note transcript pages; subsequent pages add cursor_id internally"). Params(map[string]interface{}{ "format": transcriptFormat, "page_size": transcriptPageSize, "locale": locale, }). Set("transcript_format", transcriptFormat). Set("locale", locale). Set("note", "CLI first checks note_display_type via note detail, then paginates internally (cursor_id) and saves the full unified transcript to a file") }, Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { noteID := strings.TrimSpace(runtime.Str("note-id")) transcriptFormat := runtime.Str("transcript-format") locale := resolveTranscriptLocale(runtime) outPath := strings.TrimSpace(runtime.Str("output")) if outPath == "" { outPath = defaultTranscriptPath(noteID, transcriptFormat) } if !runtime.Bool("overwrite") { if _, statErr := runtime.FileIO().Stat(outPath); statErr == nil { precondition := errs.NewValidationError(errs.SubtypeFailedPrecondition, "output file already exists: %s", outPath). WithHint("Pass --overwrite to replace the existing file") if strings.TrimSpace(runtime.Str("output")) != "" { precondition = precondition.WithParam("--output") } return precondition } } if err := ensureUnifiedNote(ctx, runtime, noteID); err != nil { return err } content, err := fetchUnifiedTranscript(ctx, runtime, noteID, transcriptFormat, locale) if err != nil { return err } saved, err := runtime.FileIO().Save(outPath, fileio.SaveOptions{}, bytes.NewReader(content)) if err != nil { return common.WrapSaveErrorTyped(err) } resolved, rerr := runtime.FileIO().ResolvePath(outPath) if rerr != nil || resolved == "" { resolved = outPath } runtime.OutFormat(map[string]any{ "note_id": noteID, "transcript_format": transcriptFormat, "transcript_file": resolved, "size_bytes": saved.Size(), }, nil, nil) return nil }, }
NoteTranscript fetches the full unified transcript and saves it to a file.
Functions ¶
Types ¶
type Detail ¶
type Detail struct {
NoteID string
CreatorID string
CreateTime string
DisplayType string // unknown | normal | unified
NoteDocToken string
VerbatimDocToken string
}
Detail is the parsed note detail shared by `note +detail` and `vc +notes`.
func FetchDetail ¶
FetchDetail queries GET /open-apis/vc/v1/notes/{note_id} and parses the note object. API errors are returned as typed errs.* values so callers can enrich user guidance without downgrading the envelope.