Skip to content

feat(gateway): add LINE quick reply approvals - #35682

Open
aaronlin wants to merge 1 commit into
NousResearch:mainfrom
aaronlin:feat/line-quick-reply-approvals
Open

feat(gateway): add LINE quick reply approvals#35682
aaronlin wants to merge 1 commit into
NousResearch:mainfrom
aaronlin:feat/line-quick-reply-approvals

Conversation

@aaronlin

@aaronlin aaronlin commented May 31, 2026

Copy link
Copy Markdown

What does this PR do?

Adds LINE quick-reply prompts for gateway approval flows, while keeping the actual decision payloads on the existing slash-command path.

LINE users now get quick replies for dangerous command approvals and destructive slash confirmations. The visible labels are localized through Hermes i18n (display.language) with LINE-specific overrides via LINE_LANGUAGE, LINE_LOCALE, extra.language, or extra.locale. The quick-reply message text remains stable (/approve, /approve session, /approve always, /deny, /always, /cancel) so the gateway's existing approval handlers continue to resolve the flow.

This PR intentionally does not include the LINE media enum fix; that is split into #35681 to keep both PRs focused.

Related Issue

No issue filed.

Related prior PRs found during duplicate search:

This PR differs by using LINE Quick Reply message actions that feed the existing slash-command approval path, plus locale-aware labels and focused adapter tests.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • plugins/platforms/line/adapter.py
    • Added quick-reply message construction helper.
    • Added LINE send_exec_approval() support for dangerous command approvals.
    • Added LINE send_slash_confirm() support for destructive slash confirmations.
    • Added shared pre-built LINE message-object send helper with reply-token-first behavior and push fallback.
    • Added LINE locale override resolution.
  • plugins/platforms/line/plugin.yaml
    • Added optional setup metadata for LINE_LANGUAGE and LINE_LOCALE.
  • locales/*.yaml
    • Added gateway.line_quick_reply.* labels across all locale catalogs.
  • tests/gateway/test_line_quick_reply.py
    • Added coverage for reply-token usage, push fallback, quick-reply slash payloads, and Traditional Chinese labels.

How to Test

  1. Run syntax checks:
    • python3 -m py_compile plugins/platforms/line/adapter.py tests/gateway/test_line_quick_reply.py agent/i18n.py
  2. Run diff hygiene:
    • git diff --check
  3. Confirm locale/setup coverage:
    • rg -l "line_quick_reply:" locales
    • rg -l " deny:" locales
    • rg -n "LINE_LANGUAGE|LINE_LOCALE" plugins/platforms/line/plugin.yaml
  4. Run the targeted regression test:
    • scripts/run_tests.sh tests/gateway/test_line_quick_reply.py
  5. Optional broader gateway coverage:
    • scripts/run_tests.sh tests/gateway
  6. In CI or a complete local dev environment, run the full suite:
    • pytest tests/ -q

Note: Full pytest tests/ -q was not completed locally. Broader gateway coverage was attempted and has one unrelated local failure in tests/gateway/test_shutdown_forensics.py::TestSpawnAsyncDiagnostic::test_spawns_subprocess_and_writes_output.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS local checkout; targeted LINE quick-reply test passed; gateway suite attempted with one unrelated shutdown-forensics failure

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A: updated plugins/platforms/line/plugin.yaml setup metadata
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A: N/A, LINE plugin setup metadata is in plugin.yaml
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A: N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A: pure Python adapter/i18n changes, no platform-specific primitives
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A: N/A

Screenshots / Logs

N/A. Local checks run on this branch:

python3 -m py_compile plugins/platforms/line/adapter.py tests/gateway/test_line_quick_reply.py agent/i18n.py: passed
git diff --check: passed
rg locale/setup checks: passed
scripts/run_tests.sh tests/gateway/test_line_quick_reply.py: 4 passed
scripts/run_tests.sh tests/gateway: 6062 passed, 1 unrelated failure

Failure:
tests/gateway/test_shutdown_forensics.py::TestSpawnAsyncDiagnostic::test_spawns_subprocess_and_writes_output
assert pid is not None and pid > 0

@alt-glitch alt-glitch added type/feature New feature or request comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have labels May 31, 2026
@aaronlin
aaronlin marked this pull request as ready for review May 31, 2026 04:24

@teknium1 teknium1 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.

Thanks for the focused LINE UX improvement. Current main still has no LINE send_exec_approval or send_slash_confirm override (plugins/platforms/line/adapter.py:1079-1146), so the feature remains useful.

Problems

  • plugins/platforms/line/adapter.py:1139-1140 emits /always and /cancel, but neither is a registered command (hermes_cli/commands.py:64-255). should_bypass_active_session() only bypasses resolvable commands (hermes_cli/commands.py:388-408), so an active session queues these replies before the slash-confirm interceptor at gateway/run.py:9127-9153 can resolve them.
  • The new direct-send path at plugins/platforms/line/adapter.py:1197 leaves a current slow-response _pending_buttons entry live. LineAdapter.send() then caches the next normal response instead of delivering it (plugins/platforms/line/adapter.py:1095-1102). The new test fixture omits _pending_buttons and _cache (tests/gateway/test_line_quick_reply.py:33-38), so it misses this interaction.

Suggested changes

  • Make pending slash-confirm replies bypass active-session routing generically, including Always and Cancel, and test all three quick-reply choices during an active session.
  • Define and test the slow-response-cache interaction so approval acknowledgement and final output remain deliverable.

Automated hermes-sweeper review.

_text_message(text),
[
(self._label("allow_once"), "/approve"),
(self._label("always_allow"), "/always"),

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.

/always and /cancel are not registered slash commands on current main, so should_bypass_active_session() returns false. When the session is active, BasePlatformAdapter queues these replies before the runner's slash-confirm interceptor can see them; the Always and Cancel chips need a generic active-session dispatch path or a callback-based flow.

if not self._client:
return SendResult(success=False, error="LINE adapter not connected")

token, used_reply = self._consume_reply_token(chat_id)

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.

This direct path does not clear an existing LINE _pending_buttons slow-response cache entry. On current main, the acknowledgement/final response subsequently sent through send() is cached instead of delivered. Handle that state and add coverage with _pending_buttons plus _cache initialized.

@teknium1 teknium1 added 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:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026
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-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 type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants