Skip to content

feat(vc): extract note doc tokens from calendar event relation API#333

Merged
Ren1104 merged 4 commits intomainfrom
feat/calendar-to-notes
Apr 9, 2026
Merged

feat(vc): extract note doc tokens from calendar event relation API#333
Ren1104 merged 4 commits intomainfrom
feat/calendar-to-notes

Conversation

@Ren1104
Copy link
Copy Markdown
Collaborator

@Ren1104 Ren1104 commented Apr 8, 2026

Summary

The --calendar-event-ids path in vc +notes now extracts meeting_notes and ai_meeting_notes doc tokens directly from the mget_instance_relation_info API response, in addition to the existing meeting_id → note detail chain. Tokens from both sources are deduplicated before output.

Changes

  • resolveMeetingIDsFromCalendarEvent: returns *eventRelationInfo (was []string), requests need_meeting_notes / need_ai_meeting_notes when needNotes=true
  • fetchNoteByCalendarEventID: merges doc tokens from both sources with deduplication; falls back to mget tokens when meeting chain fails
  • vc_recording.go: adapted to new function signature (needNotes=false, no behavior change)
  • Tests: 7 new tests covering extractStringSlice, deduplicateDocTokens, filterUnseen, calendar path integration (dedup + fallback), and request body verification

Test plan

  • Unit tests for new helper functions (extractStringSlice, toStringSlice, filterUnseen, deduplicateDocTokens)
  • Integration test: calendar path dedup (meeting_notes overlapping with note_doc_token)
  • Integration test: fallback when meeting chain fails but mget returns tokens
  • Integration test: needNotes=true sends correct request body fields
  • All existing tests pass (go test ./shortcuts/vc/)
  • Manual verification against real calendar event with linked document

Summary by CodeRabbit

  • New Features

    • Return user-linked meeting notes for calendar events, include them in CLI table/list outputs, and use calendar-event ID as a fallback row identifier.
  • Bug Fixes / Improvements

    • Deduplicate overlapping document tokens so duplicate notes aren't shown; preserve available notes even when some upstream fetches fail.
  • Tests

    • Added unit and integration tests for note extraction, deduplication, fallback behavior, and request-flag handling.
  • Documentation

    • Updated guidance and output schema to surface meeting notes alongside AI summaries.

@github-actions github-actions Bot added domain/vc PR touches the vc domain size/M Single-domain feat or fix with limited business impact labels Apr 8, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 8, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6febaa1c-9fa1-436d-b08b-710cd75730d2

📥 Commits

Reviewing files that changed from the base of the PR and between 2cc33c8 and 02fb2e2.

📒 Files selected for processing (4)
  • shortcuts/vc/vc_notes.go
  • shortcuts/vc/vc_notes_test.go
  • skills/lark-vc/SKILL.md
  • skills/lark-vc/references/lark-vc-notes.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • skills/lark-vc/references/lark-vc-notes.md
  • shortcuts/vc/vc_notes.go
  • skills/lark-vc/SKILL.md
  • shortcuts/vc/vc_notes_test.go

📝 Walkthrough

Walkthrough

Resolve calendar→meeting logic now returns structured relation info (meeting IDs + meeting_notes). Note-fetching seeds from relation-info, attempts meeting-chain fetches, merges first successful meeting result, deduplicates overlapping tokens, and may fall back to relation-info tokens when meeting-chain fails. Recording call sites updated to consume the new relation-info.

Changes

Cohort / File(s) Summary
Notes Logic
shortcuts/vc/vc_notes.go
Add eventRelationInfo return type; resolveMeetingIDsFromCalendarEvent gains needNotes flag and conditionally requests need_meeting_notes. Parse meeting_notes; add helpers extractStringSlice, asStringSlice, deduplicateDocTokens. Rework fetchNoteByCalendarEventID to seed from relation-info, iterate relInfo.MeetingIDs, merge first successful meeting fetch, deduplicate overlapping tokens, and preserve relation-info tokens as fallback.
Notes Tests
shortcuts/vc/vc_notes_test.go
Add unit tests for extractStringSlice, asStringSlice, deduplicateDocTokens. Add integration tests for --calendar-event-ids path verifying request body flags (need_meeting_notes), deduplication behavior, and fallback when meeting-chain API fails. Add HTTP stub helpers (calendarRelationStub, primaryCalendarStub).
Recording Call Sites & Tests
shortcuts/vc/vc_recording.go, shortcuts/vc/vc_recording_test.go
Update calls to resolveMeetingIDsFromCalendarEvent to pass extra false and receive *eventRelationInfo; consume relInfo.MeetingIDs instead of raw []string. Update tests/variables and assertions accordingly.
Docs: Skill & References
skills/lark-vc/SKILL.md, skills/lark-vc/references/lark-vc-notes.md
Document new meeting_notes output field (returned only for --calendar-event-ids), clarify note_doc_token as AI-generated minutes, adjust guidance and diagrams to include MeetingNotes.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant CalendarAPI as Calendar API\n(mget_instance_relation_info)
    participant MeetingAPI as Meeting API\n(fetch by meeting_id)
    participant NoteAPI as Note Details API\n(get_note_detail)

    Client->>CalendarAPI: mget_instance_relation_info(event_id, need_meeting_notes=true)
    CalendarAPI-->>Client: eventRelationInfo { MeetingIDs, meeting_notes[] }

    alt relation-info contains note tokens
        Client->>NoteAPI: (optional) fetch details for relation-info tokens
        NoteAPI-->>Client: note details
    end

    Client->>MeetingAPI: for each MeetingID -> fetch notes by meeting_id
    MeetingAPI-->>Client: meeting note details (note_doc_token, verbatim_doc_token, shared_doc_tokens)

    Client->>Client: merge relation-info tokens with meeting-detail tokens
    Client->>Client: deduplicate meeting_notes against note_doc_token/verbatim/shared tokens
    Client-->>Client: return merged, deduplicated note result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • zhaoleibd

Poem

🐰 I hop through events with tokens in paw,

I fetch and merge, then prune what I saw,
Meetings align and duplicates fall,
I tidy notes ’til outputs stand tall,
Hooray — the rabbit made the data law!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately and specifically describes the main change: extracting note doc tokens from the calendar event relation API for the vc +notes command.
Description check ✅ Passed The PR description follows the required template with all sections completed: Summary, Changes, Test plan with checkmarks, and Related Issues. All required information is present and well-documented.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/calendar-to-notes

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 8, 2026

Greptile Summary

This PR extends the --calendar-event-ids path in vc +notes to extract meeting_notes doc tokens directly from the mget_instance_relation_info API response, in addition to the existing meeting-ID chain. The new eventRelationInfo return type from resolveMeetingIDsFromCalendarEvent carries both meeting IDs and note tokens; deduplicateDocTokens then removes any overlap between meeting_notes and the note-detail fields, with a fallback that surfaces tokens even when the meeting chain fails entirely.

Confidence Score: 5/5

Safe to merge — all changes are correct, well-tested, and non-breaking.

No P0 or P1 findings. The deduplication logic is sound, the fallback path is correctly guarded, type handling through asStringSlice/extractStringSlice is consistent, and the prior cross-dedup concern from the previous review thread is resolved (the ai_meeting_notes path is simply not implemented, eliminating the overlap). Seven new tests provide solid coverage of the added code paths including edge cases like all-duplicates and meeting-chain failure.

No files require special attention.

Vulnerabilities

No security concerns identified. User-supplied IDs are passed through validate.EncodePathSegment before use in URL paths, and log values are sanitized via sanitizeLogValue before being written to stderr.

Important Files Changed

Filename Overview
shortcuts/vc/vc_notes.go Core logic change: resolveMeetingIDsFromCalendarEvent returns *eventRelationInfo instead of []string, fetchNoteByCalendarEventID merges two token sources with deduplication via deduplicateDocTokens. Logic is correct; minor note that meeting_notes is always extracted from the API response even when needNotes=false.
shortcuts/vc/vc_notes_test.go Seven new tests added covering extractStringSlice, deduplicateDocTokens (4 cases including all-duplicates), calendar-path dedup, fallback-on-chain-failure, and request-body verification; good coverage of the new code paths.
shortcuts/vc/vc_recording.go Adapted to the new *eventRelationInfo return type; only relInfo.MeetingIDs is consumed, needNotes=false is correctly passed. No behavioral change.
shortcuts/vc/vc_recording_test.go Existing recording tests updated to use the new relInfo.MeetingIDs accessor; all test logic is correct.
skills/lark-vc/SKILL.md Documentation updated to describe the new meeting_notes field and its semantics (user-bound notes, calendar-event-ids path only); guidance is accurate and consistent with the implementation.
skills/lark-vc/references/lark-vc-notes.md Reference doc updated to surface meeting_notes output field in examples and clarify its source; consistent with the code changes.

Sequence Diagram

sequenceDiagram
    participant CLI
    participant CalAPI as Calendar API
    participant VCAPI as VC API

    CLI->>CalAPI: POST /calendars/primary
    CalAPI-->>CLI: calendar_id

    CLI->>CalAPI: POST /events/mget_instance_relation_info (need_meeting_notes=true)
    CalAPI-->>CLI: meeting_instance_ids[] + meeting_notes[]

    note over CLI: Source 1: meeting_notes tokens stored in result

    loop for each meeting_id
        CLI->>VCAPI: GET /meetings/{meeting_id}
        VCAPI-->>CLI: note_id
        CLI->>VCAPI: GET /notes/{note_id}
        VCAPI-->>CLI: note_doc_token, verbatim_doc_token, shared_doc_tokens
        note over CLI: Source 2: merge into result then deduplicateDocTokens()
    end

    alt meeting chain all failed AND meeting_notes non-empty
        note over CLI: Fallback: return result with only meeting_notes tokens
    else meeting chain all failed AND meeting_notes empty
        note over CLI: Return error
    end
Loading

Reviews (3): Last reviewed commit: "refactor(vc): remove ai_meeting_notes co..." | Re-trigger Greptile

Comment thread shortcuts/vc/vc_notes.go Outdated
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 8, 2026

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@02fb2e23f98c975b51f95f26fd79ae87e6ff6f5f

🧩 Skill update

npx skills add larksuite/cli#feat/calendar-to-notes -y -g

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
shortcuts/vc/vc_notes.go (1)

127-130: ⚠️ Potential issue | 🟠 Major

Don't fail the needNotes path before reading relation note tokens.

Line 128 still requires meeting_instance_ids to be non-empty before meeting_notes / ai_meeting_notes are parsed. That makes the new direct-relation fallback unreachable for events where the API returns note tokens but no meeting IDs, so fetchNoteByCalendarEventID will return an error instead of the tokens.

Suggested fix
  info, _ := infos[0].(map[string]any)

- rawIDs, _ := info["meeting_instance_ids"].([]any)
- if len(rawIDs) == 0 {
- 	return nil, fmt.Errorf("no associated video meeting for this event")
- }
-
- result := &eventRelationInfo{}
+ result := &eventRelationInfo{
+ 	MeetingNotes:   extractStringSlice(info, "meeting_notes"),
+ 	AIMeetingNotes: extractStringSlice(info, "ai_meeting_notes"),
+ }
+ rawIDs, _ := info["meeting_instance_ids"].([]any)
+ if len(rawIDs) == 0 && len(result.MeetingNotes) == 0 && len(result.AIMeetingNotes) == 0 {
+ 	return nil, fmt.Errorf("no associated video meeting for this event")
+ }

  for _, mid := range rawIDs {
  	...
  }
-
- result.MeetingNotes = extractStringSlice(info, "meeting_notes")
- result.AIMeetingNotes = extractStringSlice(info, "ai_meeting_notes")

Also applies to: 149-153

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/vc/vc_notes.go` around lines 127 - 130, The early return that
errors when meeting_instance_ids is empty prevents the new direct-relation
note-token fallback from ever being used; modify the logic in the code handling
info (e.g., inside fetchNoteByCalendarEventID / the block referencing rawIDs,
meeting_notes and ai_meeting_notes) so you first attempt to read/parse
"meeting_notes" and "ai_meeting_notes" tokens and only if those are absent/empty
then fall back to inspecting "meeting_instance_ids" and returning an error if
both sources are empty. Apply the same reorder/fix to the second identical block
around the 149-153 region so the direct-relation tokens are checked before
failing on missing meeting IDs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@shortcuts/vc/vc_notes_test.go`:
- Around line 529-530: The new integration tests (e.g.,
TestNotes_CalendarPath_MeetingNotesDedup) call cmdutil.TestFactory without
isolating the CLI config, which can leak state; before creating the factory call
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) in
TestNotes_CalendarPath_MeetingNotesDedup and the other new tests that call
cmdutil.TestFactory (the other callers around the same block), or move that line
into a shared test helper so every TestFactory invocation in these tests runs
with an isolated config dir.

In `@shortcuts/vc/vc_notes.go`:
- Around line 183-188: The formatter that converts the JSON envelope to
text/table output still only renders note_doc_token, verbatim_doc_token, and
shared_doc_tokens and keys rows off meeting_id/minute_token, so add handling for
the new result keys "meeting_notes" and "ai_meeting_notes" (same place that
references note_doc_token, verbatim_doc_token, shared_doc_tokens and the row key
logic using meeting_id/minute_token) so relation-only successes include those
tokens in text and table modes; ensure the formatter emits them the same way as
the existing *_doc_token fields and include them when building rows for
relation-only results (also apply the same change where the code checks/returns
payloads around lines 208-210).

---

Outside diff comments:
In `@shortcuts/vc/vc_notes.go`:
- Around line 127-130: The early return that errors when meeting_instance_ids is
empty prevents the new direct-relation note-token fallback from ever being used;
modify the logic in the code handling info (e.g., inside
fetchNoteByCalendarEventID / the block referencing rawIDs, meeting_notes and
ai_meeting_notes) so you first attempt to read/parse "meeting_notes" and
"ai_meeting_notes" tokens and only if those are absent/empty then fall back to
inspecting "meeting_instance_ids" and returning an error if both sources are
empty. Apply the same reorder/fix to the second identical block around the
149-153 region so the direct-relation tokens are checked before failing on
missing meeting IDs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 04491c61-dc1a-4e03-b2f9-d6979f3c4dbb

📥 Commits

Reviewing files that changed from the base of the PR and between f5a8fbf and 3e1b2cc.

📒 Files selected for processing (4)
  • shortcuts/vc/vc_notes.go
  • shortcuts/vc/vc_notes_test.go
  • shortcuts/vc/vc_recording.go
  • shortcuts/vc/vc_recording_test.go

Comment thread shortcuts/vc/vc_notes_test.go
Comment thread shortcuts/vc/vc_notes.go Outdated
@Ren1104 Ren1104 requested a review from zhaoleibd April 8, 2026 12:56
@Ren1104 Ren1104 force-pushed the feat/calendar-to-notes branch from 2cc33c8 to 02fb2e2 Compare April 8, 2026 13:26
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
shortcuts/vc/vc_notes.go (1)

125-128: ⚠️ Potential issue | 🟠 Major

Allow relation-note fallback when no meeting_instance_ids are returned.

At Line 126, the function errors before considering meeting_notes. This prevents success for relation-only results even though note tokens may already be available.

🔧 Suggested patch
-	rawIDs, _ := info["meeting_instance_ids"].([]any)
-	if len(rawIDs) == 0 {
-		return nil, fmt.Errorf("no associated video meeting for this event")
-	}
-
-	result := &eventRelationInfo{}
+	result := &eventRelationInfo{
+		MeetingNotes: extractStringSlice(info, "meeting_notes"),
+	}
+	rawIDs, _ := info["meeting_instance_ids"].([]any)
+	if len(rawIDs) == 0 {
+		if needNotes && len(result.MeetingNotes) > 0 {
+			return result, nil
+		}
+		return nil, fmt.Errorf("no associated video meeting for this event")
+	}
@@
-	result.MeetingNotes = extractStringSlice(info, "meeting_notes")
-
 	return result, nil

Also applies to: 147-151

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/vc/vc_notes.go` around lines 125 - 128, The code currently returns
an error when rawIDs (from info["meeting_instance_ids"]) is empty, preventing a
fallback to relation-only notes; change the logic around the rawIDs check (the
block with rawIDs, _ := info["meeting_instance_ids"]) to not immediately return
an error but instead check for available meeting_notes (info["meeting_notes"])
and proceed with relation-note processing when notes exist, only returning an
error if both meeting_instance_ids and meeting_notes are absent; apply the same
fix to the similar block at lines handling the second rawIDs check (the repeated
rawIDs/meeting_instance_ids block) so both places attempt meeting_notes fallback
before erroring.
♻️ Duplicate comments (1)
shortcuts/vc/vc_notes_test.go (1)

515-517: ⚠️ Potential issue | 🟠 Major

Isolate CLI config state in the new TestFactory-based tests.

These new tests create factories without setting an isolated config directory, which can make them order-dependent and leak machine-local state.

🔧 Suggested patch
 func TestNotes_CalendarPath_MeetingNotesDedup(t *testing.T) {
+	t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
 	f, stdout, _, reg := cmdutil.TestFactory(t, defaultConfig())
@@
 func TestNotes_CalendarPath_FallbackWhenMeetingChainFails(t *testing.T) {
+	t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
 	f, stdout, _, reg := cmdutil.TestFactory(t, defaultConfig())
@@
 func TestNotes_CalendarPath_NeedNotes_RequestBody(t *testing.T) {
+	t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
 	f, _, _, reg := cmdutil.TestFactory(t, defaultConfig())
 	warmTokenCache(t)

As per coding guidelines, **/*_test.go: Isolate config state in Go tests by using t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()).

Also applies to: 552-554, 592-594

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/vc/vc_notes_test.go` around lines 515 - 517, The tests that call
cmdutil.TestFactory (e.g., TestNotes_CalendarPath_MeetingNotesDedup) don't
isolate CLI config state and may leak machine-local settings; add
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) at the start of each affected
test (including TestNotes_CalendarPath_MeetingNotesDedup and the sibling tests
that also call cmdutil.TestFactory) so each test uses its own temporary config
directory before calling cmdutil.TestFactory.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@shortcuts/vc/vc_notes.go`:
- Around line 125-128: The code currently returns an error when rawIDs (from
info["meeting_instance_ids"]) is empty, preventing a fallback to relation-only
notes; change the logic around the rawIDs check (the block with rawIDs, _ :=
info["meeting_instance_ids"]) to not immediately return an error but instead
check for available meeting_notes (info["meeting_notes"]) and proceed with
relation-note processing when notes exist, only returning an error if both
meeting_instance_ids and meeting_notes are absent; apply the same fix to the
similar block at lines handling the second rawIDs check (the repeated
rawIDs/meeting_instance_ids block) so both places attempt meeting_notes fallback
before erroring.

---

Duplicate comments:
In `@shortcuts/vc/vc_notes_test.go`:
- Around line 515-517: The tests that call cmdutil.TestFactory (e.g.,
TestNotes_CalendarPath_MeetingNotesDedup) don't isolate CLI config state and may
leak machine-local settings; add t.Setenv("LARKSUITE_CLI_CONFIG_DIR",
t.TempDir()) at the start of each affected test (including
TestNotes_CalendarPath_MeetingNotesDedup and the sibling tests that also call
cmdutil.TestFactory) so each test uses its own temporary config directory before
calling cmdutil.TestFactory.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 87917636-3c7b-4087-bf29-8286561699ab

📥 Commits

Reviewing files that changed from the base of the PR and between ab8162d and 2cc33c8.

📒 Files selected for processing (4)
  • shortcuts/vc/vc_notes.go
  • shortcuts/vc/vc_notes_test.go
  • skills/lark-vc/SKILL.md
  • skills/lark-vc/references/lark-vc-notes.md
✅ Files skipped from review due to trivial changes (2)
  • skills/lark-vc/SKILL.md
  • skills/lark-vc/references/lark-vc-notes.md

@Ren1104 Ren1104 merged commit 35108e1 into main Apr 9, 2026
16 checks passed
@Ren1104 Ren1104 deleted the feat/calendar-to-notes branch April 9, 2026 03:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain/vc PR touches the vc domain size/M Single-domain feat or fix with limited business impact

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants