Skip to content

feat(meetings): calendar-triggered auto-join prompt#3522

Closed
Sathvik-1007 wants to merge 10 commits into
tinyhumansai:mainfrom
Sathvik-1007:feat/meeting-assistant-pr1-calendar-autojoin
Closed

feat(meetings): calendar-triggered auto-join prompt#3522
Sathvik-1007 wants to merge 10 commits into
tinyhumansai:mainfrom
Sathvik-1007:feat/meeting-assistant-pr1-calendar-autojoin

Conversation

@Sathvik-1007

@Sathvik-1007 Sathvik-1007 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

What

Calendar watch + auto-join prompt for Google Meet meetings. Depends on PR-0 (#3516, merged).

Changes

Bug fix: collect_calendar_meetings stored htmlLink in deep_link when both links existed — Meet URL was lost. Now extracts hangoutLink separately into PendingEvent.meet_url.

New: agent_meetings/calendar.rsidentify_meet_meetings filters events whose meet_url matches allowed conferencing hosts.

Planner policy routing: For meetings with a meet_url, creates a MeetingSession (Pending) and evaluates auto_join_policy:

  • Never — no action buttons
  • Always — emits MeetingAutoJoinTriggered domain event (transparency notification, no buttons)
  • AskEachTime — publishes notification with Add OpenHuman / Not this one / Always join buttons

New RPC: openhuman.agent_meetings_notification_action handles user clicks:

  • join_meeting — joins in listen-only mode with correlation_id
  • skip_meeting — transitions session to Ended
  • always_join — flips config to Always + joins

Frontend: Socket listener passes actions from core_notification events. Notifications page renders action buttons and calls the new RPC.

Testing

  • Rust: URL extraction, policy routing branches (unit tests in calendar.rs)
  • Schema: registered controllers match (updated assertion)
  • TypeScript: compiles clean, prettier passes

Validation Run

  • cargo fmt --all -- --check
  • TypeScript compilation (tsc --noEmit)
  • Prettier

Closes #3507

Summary by CodeRabbit

  • New Features
    • Meeting notifications now include interactive action buttons allowing users to join, skip, or configure automatic join preferences directly from notifications
    • Improved detection and support for meeting links in calendar invitations, including Google Meet, Zoom, and Microsoft Teams
    • Added configurable automatic meeting join capability based on user preferences

- fix: extract hangoutLink separately from htmlLink in collectors
- add meet_url field to PendingEvent
- new calendar.rs: identify_meet_meetings filter
- planner evaluates auto_join_policy per meeting event
- new RPC: agent_meetings_notification_action (join/skip/always)
- frontend: pass actions through socket, render action buttons
- MeetingAutoJoinTriggered domain event for Always policy

Closes tinyhumansai#3507
@Sathvik-1007 Sathvik-1007 requested a review from a team June 8, 2026 22:35
@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ced24643-984b-4fa4-a150-a4ab2b8a08e2

📥 Commits

Reviewing files that changed from the base of the PR and between 78c8a7d and 0d336ce.

📒 Files selected for processing (1)
  • .github/workflows/pr-ci.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/pr-ci.yml

📝 Walkthrough

Walkthrough

Adds end-to-end meeting auto-join prompt support: PendingEvent gains a meet_url field populated from hangoutLink, a new calendar.rs module filters events by allowed conferencing hosts, the heartbeat planner builds meeting action buttons or triggers auto-join based on auto_join_policy, a new handle_notification_action RPC handles join/skip/always-join, and the frontend notification UI renders and dispatches those action buttons.

Changes

Meeting Notification Actions

Layer / File(s) Summary
Data Contracts & Types
src/openhuman/subconscious/heartbeat/planner/types.rs, src/openhuman/agent_meetings/calendar.rs, src/core/event_bus/events.rs
PendingEvent gains meet_url: Option<String>, CalendarMeeting struct and host allowlist are introduced, and DomainEvent gains the MeetingAutoJoinTriggered variant with domain and variant-name routing.
Calendar Meeting Identification
src/openhuman/agent_meetings/calendar.rs
identify_meet_meetings filters PendingEvents by meet_url against an allowed-host list (Google Meet, Zoom, Teams) via is_allowed_host with subdomain normalization; unit tests cover all host cases.
Heartbeat Collector Meet URL Extraction
src/openhuman/subconscious/heartbeat/planner/collectors.rs
Calendar extraction captures meet_url from hangoutLink separately, uses htmlLink for deep_link with meet_url fallback; non-calendar collectors set meet_url: None.
Planner Action Building & Policy Routing
src/openhuman/subconscious/heartbeat/planner/mod.rs
build_meeting_actions creates an idempotent MeetingSession and routes on auto_join_policy: publishes MeetingAutoJoinTriggered for Never/Always, returns three CoreNotificationAction buttons for AskEachTime; evaluate_and_dispatch passes computed actions to CoreNotificationEvent; tests updated and new policy-branch tests added.
Backend Notification Action RPC Handler
src/openhuman/agent_meetings/ops.rs, src/openhuman/agent_meetings/schemas.rs
handle_notification_action routes join_meeting/skip_meeting/always_join actions, updates session status, and persists auto_join_policy = Always when applicable; schemas.rs registers the notification_action controller; error-path tests added.
Frontend Notification Service & Action UI
app/src/lib/nativeNotifications/service.ts, app/src/pages/Notifications.tsx
CoreNotificationPayload gains actions; socket and test handlers forward it; Notifications.tsx renders action buttons, deduplicates concurrent clicks via pendingActionsRef, marks notifications read, and calls openhuman.agent_meetings_notification_action via callCoreRpc.

CI Coverage Cleanup

Layer / File(s) Summary
CI Stale Artifact Cleanup Step
.github/workflows/pr-ci.yml
New rust-core-coverage step removes target/llvm-cov-target, incremental, and build/debug/release directories before coverage runs, then prints disk diagnostics.

Sequence Diagram(s)

sequenceDiagram
  rect rgba(200, 230, 255, 0.5)
    note over Planner: Backend heartbeat tick
    Planner->>CalendarIdentifier: identify_meet_meetings(pending_events)
    CalendarIdentifier-->>Planner: Vec<CalendarMeeting>
    Planner->>MeetingStore: create/get MeetingSession (idempotent)
    alt auto_join_policy == AskEachTime
      Planner->>EventBus: publish CoreNotificationEvent with join/skip/always_join actions
    else auto_join_policy == Always or Never
      Planner->>EventBus: publish MeetingAutoJoinTriggered
    end
  end
  rect rgba(230, 255, 200, 0.5)
    note over Socket,Notifications: Frontend
    EventBus->>Socket: core_notification {actions}
    Socket->>NotificationService: forward with actions
    NotificationService->>Notifications: dispatch notification item with actions
    Notifications->>Notifications: render action buttons
    Notifications->>RPCHandler: callCoreRpc agent_meetings_notification_action {action_id, payload}
    RPCHandler->>MeetingStore: update session status
    RPCHandler-->>Notifications: ok true
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • tinyhumansai/openhuman#3516: Introduced the NotificationAction and CoreNotificationAction types and the optional actions field on NotificationItem/CoreNotificationEvent that this PR propagates and renders.

Poem

🐇 Hop hop, a meeting's near!
The calendar whispers in my ear,
"Join or skip, the choice is yours,"
Three bright buttons open doors.
With meet_url plumbed and policies set,
No Google Meet shall be missed yet! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(meetings): calendar-triggered auto-join prompt' accurately summarizes the main change: adding calendar-triggered auto-join notifications for Google Meet meetings.
Linked Issues check ✅ Passed All coding objectives from issue #3507 are met: hangoutLink extraction into meet_url, identify_meet_meetings implementation, planner policy routing with MeetingSession creation, RPC handler with join/skip/always-join semantics, frontend action button rendering, and Rust/Vitest coverage.
Out of Scope Changes check ✅ Passed All changes align with #3507 scope. The CI workflow modification (target/ cleanup for coverage) is a supporting change for build reliability and falls within reasonable scope.
Docstring Coverage ✅ Passed Docstring coverage is 82.93% which is sufficient. The required threshold is 80.00%.

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


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot added feature Net-new user-facing capability or product behavior. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. labels Jun 8, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (2)
app/src/lib/nativeNotifications/service.ts (1)

42-42: ⚡ Quick win

Use a named interface for notification actions.

The inline { actionId; label; payload? } object type should be extracted to an interface for guideline compliance.

As per coding guidelines, **/*.{ts,tsx} should use interface for defining object shapes in TypeScript.

Suggested fix
+interface CoreNotificationAction {
+  actionId: string;
+  label: string;
+  payload?: unknown;
+}
+
 interface CoreNotificationPayload {
   id: string;
   category: NotificationCategory;
   title: string;
   body: string;
   deep_link?: string | null;
   timestamp_ms: number;
-  actions?: Array<{ actionId: string; label: string; payload?: unknown }>;
+  actions?: CoreNotificationAction[];
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/lib/nativeNotifications/service.ts` at line 42, Extract the inline
object type used for notification actions into a named interface (e.g., declare
interface NotificationAction { actionId: string; label: string; payload?:
unknown }) and then replace the inline type in the `actions?: Array<{ actionId:
string; label: string; payload?: unknown }>;` declaration with `actions?:
NotificationAction[]`; update any imports/exports or other references in the
same file so the new `NotificationAction` interface is used consistently (look
for `actions` in service.ts and any related types in this module).

Source: Coding guidelines

src/openhuman/agent_meetings/ops.rs (1)

291-377: ⚡ Quick win

Add debug diagnostics to the new notification-action flow.

This new/changed flow currently has no entry/branch/error tracing, which makes action failures hard to debug.

As per coding guidelines, new/changed Rust flows under src/openhuman/**/*.rs should include debug/trace logging for entry/exit, branches, and errors with stable prefixes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/agent_meetings/ops.rs` around lines 291 - 377, The handler
lacks diagnostics: update handle_notification_action to emit stable-prefixed
debug/trace logs at entry (log action_id, meeting_id, meet_url and timestamp),
before each branch (log entering "join_meeting", "skip_meeting", "always_join"),
and on all error paths and after successful outcomes; use the repository logging
facility (e.g., tracing::debug/trace/error) with a consistent prefix like
"[agent_meetings]" and include unique identifiers (action_id, meeting_id,
correlation_id) and the function name handle_notification_action so failures and
branch decisions are observable; also log config load/save and
store::update_session_status results and the final returned outcome.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/pages/Notifications.tsx`:
- Around line 168-180: The action buttons currently render raw action.label;
change them to use the localization hook useT() and translate by actionId (e.g.,
t(`notifications.actions.${action.actionId}`)), ensuring useT is imported/used
in Notifications (or the component rendering item.actions) and provide a
fallback to action.label or a sensible default if the translation key is
missing; keep onclick behavior (handleAction(item, action.actionId,
action.payload)) unchanged.
- Around line 61-74: handleAction is vulnerable to duplicate RPCs when the user
clicks repeatedly; add an in-flight guard (e.g., a component-scoped Set stored
in a ref like pendingActionsRef) and use a composite key
`${item.id}:${actionId}` to short-circuit and return immediately if the key is
already pending, add the key to the set before awaiting callCoreRpc, and ensure
the key is removed in a finally block so retries are possible; apply the same
pattern to the other handler at the 171-177 block and keep using markRead and
callCoreRpc as currently named.

In `@src/openhuman/agent_meetings/ops.rs`:
- Around line 326-335: The code sets session status to
MeetingSessionStatus::Joined via super::store::update_session_status before
awaiting handle_join, which can leave state inconsistent if handle_join fails;
change the flow so you first call handle_join(join_params).await and only upon
its Ok result call super::store::update_session_status(&config, &meeting_id,
super::types::MeetingSessionStatus::Joined, now_ms), propagating errors from
update_session_status as before; apply the same fix to the other occurrence
referenced (the block around the handle_join call at the 365-374 region) so both
join paths update status only after handle_join succeeds.
- Around line 299-308: Current code defaults payload fields meeting_id and
meet_url to empty strings which masks missing required data; update the handler
logic that reads meeting_id and meet_url so it returns an explicit error when
required fields are absent instead of unwrap_or(""), validating per action:
require meeting_id for the "skip" action and require both meeting_id and
meet_url for "join" and "always_join" actions; locate the occurrences where
meeting_id and meet_url are extracted (variables named meeting_id and meet_url
around the blocks handling skip/join/always_join and the repeated occurrences at
the other extraction sites) and replace the unwrap_or("") extraction with proper
Option checks that produce an Err or early-return with a clear error message
indicating the missing field(s).

In `@src/openhuman/subconscious/heartbeat/planner/mod.rs`:
- Around line 155-157: The auto-join dispatch is being triggered unconditionally
by build_meeting_actions and publishes MeetingAutoJoinTriggered for
AutoJoin::Always too early and possibly multiple times; update the logic so that
build_meeting_actions (or its caller) only considers and publishes
MeetingAutoJoinTriggered when the event.stage corresponds to the "happening now"
or "final_call" states (e.g., match the event.stage enum cases used elsewhere),
and add an idempotency guard before publishing (check an existing flag/marker on
the event or ensure the action list does not already contain
MeetingAutoJoinTriggered) so the event only fires once per meeting.
- Around line 235-242: The code currently treats any error from
meetings_store::create_session(config, &session) as a benign "already exists"
case; instead, match the returned error (from meetings_store::create_session) to
distinguish a UNIQUE-constraint/duplicate-session error from other DB failures:
if it's the duplicate/unique error, keep the existing tracing::debug for
meeting_id and continue, but for any other error log it at error level and
propagate/fail early (return Err or bail) so you do not emit buttons/events tied
to meeting_id. Locate meetings_store::create_session and the surrounding planner
code that uses meeting_id and session and implement this error-kind check (use
the concrete error variant/type exported by meetings_store or inspect SQL error
code) before proceeding.

---

Nitpick comments:
In `@app/src/lib/nativeNotifications/service.ts`:
- Line 42: Extract the inline object type used for notification actions into a
named interface (e.g., declare interface NotificationAction { actionId: string;
label: string; payload?: unknown }) and then replace the inline type in the
`actions?: Array<{ actionId: string; label: string; payload?: unknown }>;`
declaration with `actions?: NotificationAction[]`; update any imports/exports or
other references in the same file so the new `NotificationAction` interface is
used consistently (look for `actions` in service.ts and any related types in
this module).

In `@src/openhuman/agent_meetings/ops.rs`:
- Around line 291-377: The handler lacks diagnostics: update
handle_notification_action to emit stable-prefixed debug/trace logs at entry
(log action_id, meeting_id, meet_url and timestamp), before each branch (log
entering "join_meeting", "skip_meeting", "always_join"), and on all error paths
and after successful outcomes; use the repository logging facility (e.g.,
tracing::debug/trace/error) with a consistent prefix like "[agent_meetings]" and
include unique identifiers (action_id, meeting_id, correlation_id) and the
function name handle_notification_action so failures and branch decisions are
observable; also log config load/save and store::update_session_status results
and the final returned outcome.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3197e9e8-f844-4ec7-b8e1-aa4dd05f53f7

📥 Commits

Reviewing files that changed from the base of the PR and between 2f32481 and defb978.

📒 Files selected for processing (10)
  • app/src/lib/nativeNotifications/service.ts
  • app/src/pages/Notifications.tsx
  • src/core/event_bus/events.rs
  • src/openhuman/agent_meetings/calendar.rs
  • src/openhuman/agent_meetings/mod.rs
  • src/openhuman/agent_meetings/ops.rs
  • src/openhuman/agent_meetings/schemas.rs
  • src/openhuman/subconscious/heartbeat/planner/collectors.rs
  • src/openhuman/subconscious/heartbeat/planner/mod.rs
  • src/openhuman/subconscious/heartbeat/planner/types.rs

Comment thread app/src/pages/Notifications.tsx
Comment thread app/src/pages/Notifications.tsx
Comment thread src/openhuman/agent_meetings/ops.rs Outdated
Comment thread src/openhuman/agent_meetings/ops.rs
Comment thread src/openhuman/subconscious/heartbeat/planner/mod.rs
Comment thread src/openhuman/subconscious/heartbeat/planner/mod.rs
…stage gate

- move session status update after handle_join succeeds
- validate meeting_id/meet_url presence, return error if missing
- gate auto-join dispatch to final_call/happening_now stages
- add tracing::debug to notification_action handler
- fix E0603: use re-exported AutoJoinPolicy path
- extract NotificationAction interface in service.ts
- add in-flight guard to prevent duplicate action RPCs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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)
app/src/pages/Notifications.tsx (1)

62-78: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add user feedback for RPC failures.

The RPC call at line 69 has no error handling. When invoked via void handleAction(...) on line 180, any RPC failure will be silently swallowed, leaving the user with no indication whether their action (join/skip/always join) succeeded or failed.

💬 Proposed fix: add try-catch and user feedback
 const handleAction = useCallback(
   async (item: NotificationItem, actionId: string, payload?: unknown) => {
     const key = `${item.id}:${actionId}`;
     if (pendingActionsRef.current.has(key)) return;
     pendingActionsRef.current.add(key);
     if (!item.read) dispatch(markRead({ id: item.id }));
     try {
       await callCoreRpc({
         method: 'openhuman.agent_meetings_notification_action',
         params: { notification_id: item.id, action_id: actionId, payload },
       });
+      // Optional: show success toast
+    } catch (err) {
+      console.error('[Notifications] action failed', err);
+      // TODO: show error toast to user
     } finally {
       pendingActionsRef.current.delete(key);
     }
   },
   [dispatch]
 );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/pages/Notifications.tsx` around lines 62 - 78, The handleAction
callback currently awaits callCoreRpc without handling errors so failures are
silent; wrap the RPC call in a try-catch around callCoreRpc inside handleAction,
log the error (console.error) and surface a user-visible error (e.g., dispatch a
toast/notification or show an alert) mentioning the failed action and
notification id, and if you made optimistic changes (dispatch(markRead({ id:
item.id }))) consider reverting or informing the user on failure; keep the
existing finally block that deletes the key from pendingActionsRef.current to
ensure cleanup.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@app/src/pages/Notifications.tsx`:
- Around line 62-78: The handleAction callback currently awaits callCoreRpc
without handling errors so failures are silent; wrap the RPC call in a try-catch
around callCoreRpc inside handleAction, log the error (console.error) and
surface a user-visible error (e.g., dispatch a toast/notification or show an
alert) mentioning the failed action and notification id, and if you made
optimistic changes (dispatch(markRead({ id: item.id }))) consider reverting or
informing the user on failure; keep the existing finally block that deletes the
key from pendingActionsRef.current to ensure cleanup.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 59323233-a5dc-4d6f-8be7-0df2c4d38d6c

📥 Commits

Reviewing files that changed from the base of the PR and between defb978 and 1f72e66.

📒 Files selected for processing (4)
  • app/src/lib/nativeNotifications/service.ts
  • app/src/pages/Notifications.tsx
  • src/openhuman/agent_meetings/ops.rs
  • src/openhuman/subconscious/heartbeat/planner/mod.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • app/src/lib/nativeNotifications/service.ts
  • src/openhuman/subconscious/heartbeat/planner/mod.rs
  • src/openhuman/agent_meetings/ops.rs

@coderabbitai coderabbitai Bot added the agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. label Jun 9, 2026
@Sathvik-1007

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Sathvik-1007

Copy link
Copy Markdown
Contributor Author

@coderabbitai resolve

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Comments resolved and changes approved.

@M3gA-Mind

Copy link
Copy Markdown
Collaborator

Thanks for the contribution! Closing this as a duplicate — the same change is already on main via #3721 (merged), which resolves this issue.

If your version covers something the merged PR doesn't, just comment and we'll gladly reopen. 🙏

@M3gA-Mind M3gA-Mind closed this Jun 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. feature Net-new user-facing capability or product behavior. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Meeting Assistant] PR-1: Calendar-triggered auto-join prompt

2 participants