Skip to content

feat(google-chat): handle card click callbacks - #36069

Open
aeyeopsdev wants to merge 8 commits into
NousResearch:mainfrom
AeyeOps:feat/google-chat-card-click-callbacks
Open

feat(google-chat): handle card click callbacks#36069
aeyeopsdev wants to merge 8 commits into
NousResearch:mainfrom
AeyeOps:feat/google-chat-card-click-callbacks

Conversation

@aeyeopsdev

@aeyeopsdev aeyeopsdev commented May 31, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Handles authenticated Google Chat card-click callbacks, including resolving built-in clarify() card choices and forwarding unknown card actions as structured agent-visible events.

This completes the Google Chat card interaction path so card buttons can produce authenticated gateway events instead of only rendering static cards.

Depends on #36035, #36061, and #36068. This draft is intentionally stacked; after the dependencies land, this branch should be rebased so the final diff contains only card-click callback handling.

Related Google Chat PRs: #36027, #36035, #36061, #36068.

Related Issue

N/A — follow-up to the Google Chat HTTP callback and clarify-card rendering work.

Type of Change

  • ✨ New feature (non-breaking change that adds functionality)
  • ✅ Tests (adding or improving test coverage)

Changes Made

  • plugins/platforms/google_chat/adapter.py: parse Google Chat card-click/add-on callback payloads.
  • plugins/platforms/google_chat/adapter.py: resolve hermes_clarify button choices through tools.clarify_gateway.
  • plugins/platforms/google_chat/adapter.py: apply adapter/gateway authorization checks before resolving clarify card clicks.
  • plugins/platforms/google_chat/adapter.py: dispatch unknown card actions to the agent as synthesized command events.
  • tests/gateway/test_google_chat.py: cover action parsing, add-on normalization, generic card-click dispatch, clarify resolution, and unauthorized clarify-click rejection.

How to Test

  1. python -m py_compile plugins/platforms/google_chat/adapter.py tests/gateway/test_google_chat.py gateway/platforms/api_server.py gateway/run.py
  2. git diff --check
  3. scripts/run_tests.sh tests/gateway/test_api_server.py tests/gateway/test_google_chat.py
  4. python /root/.codex/skills/hermes-upstream-pr/scripts/pr_preflight.py --base HEAD~1

Checklist

Code

  • I've read the Contributing Guide.
  • My commit message follows Conventional Commits.
  • I searched for existing PRs to make sure this isn't a duplicate.
  • My PR contains only changes related to this feature slice, but is currently stacked while draft.
  • I've added tests for my changes.
  • I've tested on Linux.

Documentation & Housekeeping

  • Documentation update N/A.
  • cli-config.yaml.example update N/A.
  • CONTRIBUTING.md / AGENTS.md update N/A.
  • Cross-platform impact considered: adapter callback parsing and tests only.
  • Tool descriptions/schemas update N/A.

Related PRs

Screenshots / Logs

Validation passed locally:

scripts/run_tests.sh tests/gateway/test_api_server.py tests/gateway/test_google_chat.py
337 tests passed, 0 failed

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins comp/gateway Gateway runner, session dispatch, delivery labels May 31, 2026
@aeyeopsdev
aeyeopsdev force-pushed the feat/google-chat-card-click-callbacks branch from e5153d6 to 289fd8c Compare June 30, 2026 12:25
@aeyeopsdev
aeyeopsdev marked this pull request as ready for review June 30, 2026 13:00
Add _is_callback_user_authorized mirroring Telegram's contract: when the
runner _is_user_authorized path is unavailable, fall back to the
GOOGLE_CHAT_ALLOWED_USERS allowlist (comma-separated emails, '*' wildcard)
and GATEWAY_ALLOW_ALL_USERS, denying by default instead of silently letting
any card click resolve a clarify/approval. Closes the fail-open gap where a
missing auth_fn let unauthorized clicks through.
mark_awaiting_text is the 'Other (type answer)' mode-flip; calling it in
send_clarify captures the user's next message as the clarify response,
racing the button-click path. It is already called in the __other__ branch
of _dispatch_clarify_card_click — drop the send-time duplicate.
@aeyeopsdev
aeyeopsdev force-pushed the feat/google-chat-card-click-callbacks branch from 72cc52e to ec76ec7 Compare July 5, 2026 23:27
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for completing the Google Chat interaction path. The underlying gap is real: current main still ACKs card/widget events without dispatching them (plugins/platforms/google_chat/adapter.py:1211-1217).

Problems

  • This branch cannot be merged as-is (mergeable_state: dirty) and its gateway/platforms/api_server.py snapshot predates current run-lifetime work. The diff replaces current _active_run_tasks accounting (gateway/platforms/api_server.py:4005-4019) with _run_streams accounting and drops the retained-task/stop state at gateway/platforms/api_server.py:881-891. That would undo the transport-lifetime and stop fixes in 8f18fa104 and 837077dfa.
  • The branch also removes the current authenticated readiness aggregation at gateway/platforms/api_server.py:1429-1440, replacing it with an unconditional status: ok response.

Suggested changes

  • Salvage the Google Chat callback/card-click slice onto current main, preserving current API-server run control, SSE transport, and readiness behavior. Keep the focused callback tests alongside current API-server invariants.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Your whole stack has now landed on main: #36035 (HTTP inbound) via #65545, #36068 (clarify cards) via #65546, and #36061 (generic platform event callback route) via #65702 — all with your authorship preserved. This PR is the last piece. Could you rebase it onto current main? It should shrink to just the card-click handling now that the base commits are merged. Note #65702 added one hardening change on top of your route (verifiers run via asyncio.to_thread and fail closed on exceptions) — your callback dispatch should slot straight in. Happy to review as soon as it's rebased.

@GottZ GottZ left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This was generated by AI during triage.

Summary

Five PRs address the Google Chat interaction stack: #36035/#65545 make HTTP inbound possible without Pub/Sub, #36061/#65702 provide authenticated callback routing, and #36069 uniquely handles the remaining cause by dispatching card-click events that were previously only ACKed. The first two changes are already represented on main by #65545 and #65702, leaving only a clean current-main extraction of #36069's card-click logic to land.

Related pull requests

  • #36035 [closed] related — (+152/-85) — superseded by merged #65545: This relaxes Pub/Sub requirements and enables HTTP-mode configuration, but its original diff provides no callback route, authentication, or dispatch handler, so it does not by itself fix dropped card clicks. It remains relevant as the source change salvaged into #65545; the contributor keep_open review correctly identified that the original slice was not operational alone.
  • #36061 [closed] related — (+670/-86) — superseded by merged #65702: This adds the generic callback route, Google OIDC verification, and HTTP MESSAGE dispatch required before card clicks can enter the adapter, but it does not dispatch CARD_CLICKED events. It remains relevant because #65702 salvaged it and added the contributor-requested off-loop, fail-closed verifier hardening; its keep_open review identified configuration coherence and production-path coverage concerns rather than grounds to merge the old head unchanged.
  • #36069 related — (+1430/-93) — keep open, but rebase before merge: Its unique adapter diff parses card/add-on callback payloads, resolves authorized clarify choices, and forwards unknown actions, directly fixing the remaining ACK-without-dispatch cause. Consistent with the contributor keep_open review, the current stacked head must not be merged as-is because its stale API-server snapshot would regress run-lifetime and authenticated-readiness behavior; salvage only the card-click slice onto current main, preserving #65702's hardened route.
  • #65545 [merged] related — (+153/-85) — merged prerequisite/reference implementation: This is the current-main salvage of #36035, making Pub/Sub optional when HTTP inbound is configured. It removes the transport-configuration blocker but intentionally does not implement callback routing or card-click dispatch.
  • #65702 [merged] related — (+536/-3) — merged prerequisite/reference implementation: This is the current-main salvage of #36061, adding the generic authenticated platform callback route and Google Chat HTTP MESSAGE dispatch, with verifier execution moved off the event loop and exceptions failing closed. It supplies the ingress needed by #36069 but still leaves card/widget callbacks undispatched.

Duplicates

#36035 and #65545 are substantially the same HTTP-without-Pub/Sub change, with #65545 being the merged current-main salvage. #36061 and #65702 are substantially the same callback-routing change, with #65702 being the merged, hardened current-main salvage. #36069 contains those stacked bases but also has the unique card-click implementation.

Suggested consolidation

Merge #36069 only after rebasing or salvaging its focused card-click handling onto current main and verifying that #65702's off-loop fail-closed verifier plus current API-server run-lifetime, SSE, stop, and authenticated-readiness behavior remain intact. This follows the keep_open review on #36069 rather than overriding it: the diff demonstrates a real unique fix, while the contributor explicitly blocks merging the stale stacked head as-is. #36035 and #36061 are already closed and superseded by merged duplicates #65545 and #65702; no further duplicate PR needs closing.

Cross-PR triage: Reviewed 5 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 175 kB of PR diffs, 12 kB of issue/PR text, 7 kB of discussion (9 comments), 0 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants