Commit graph

52 commits

Author SHA1 Message Date
xmanrui
149f435216 fix: trim redundant quoted message metadata 2026-09-03 03:11:14 +08:00
xmanrui
2b6f4bdfb0 fix(feishu): preserve interaction card reply semantics 2026-09-03 01:12:51 +08:00
xmanrui
d4e1bd3cab Merge main into feat/feishu-interaction-cards
# Conflicts:
#	lib/index.js
2026-09-03 01:00:04 +08:00
xmanrui
3240632bef Merge main into agent/issue-88 and resolve workspace aliases 2026-09-03 00:47:38 +08:00
xmanrui
37ec6abb06 feat: support limiting session list results 2026-09-02 03:01:44 +08:00
xmanrui
94e114b9b3 fix: preserve quoted message context across channels 2026-09-02 01:27:35 +08:00
C3H3-AI
b5378500ca fix(feishu): bind card decisions to the actor and reject stale cards
Address review feedback on the interaction cards:

1. Bind card decisions to the initiating actor. The card-action operator
   (operatorOpenId) is now passed into the approval and question handlers:
   - submitByApprovalId receives { actor } so another allowed group member
     cannot approve/reject someone else's approval;
   - the answer branch requires pending.actor === operator.

2. Include the question index in the answer button action and validate it
   against the current pending question, so a stale card from an earlier
   question in a multi-question interaction cannot be applied to the next one.

3. When both the card send and the plain-text fallback fail, the error is no
   longer swallowed: it propagates so the interaction is not marked as
   presented and the existing retry/reconnect behaviour can run.

Adds regression tests for all three cases.
2026-09-02 00:18:50 +08:00
C3H3-AI
0b42ea9889 feat(feishu): interactive approval and question cards with buttons
Render Harness approval and single-choice question interactions as
interactive Feishu cards with approve/reject and answer buttons,
matching the already-available interactionCards behaviour. Cards are now
the default; set DSH_IM_INTERACTION_CARDS=0 (or interactionCards=false)
to keep the plain-text reply flow.

- bridge.mjs: approve:/reject:/answer: card actions, interactionCards
  option, gated approval render hook, interactive question presentation,
  and operationArguments/printableText helpers; refactor the inline
  question answer into #submitQuestionAnswer so both text replies and
  card buttons share one path.
- feishu-cards.mjs: approvalCard (approve/reject) and questionCard
  (option buttons) templates.
- feishu-runtime.mjs: default interactionCards from env (on).
- harness-approval.mjs: optional channel render hook + submitByApprovalId.
- i18n-en: add the new card t() keys.
- Tests: pin the plain-text reply flow in state-machine suites that
  drive it, and add dedicated card tests for the default approve/reject,
  answer buttons, and the text fallback. Full suite shows no new
  failures versus upstream.
2026-09-02 00:18:37 +08:00
evanfang0054
1a165822ac fix(feishu): rotate the streaming card before presenting in-turn interactions 2026-09-01 17:53:42 +08:00
yusuke8h
65c1c55f1a fix: [Feature] 为工作区命令增加 /ws、/wsl 和 /workspaces 别名 (#88) 2026-09-01 17:03:48 +09:00
xmanrui
840e5aa857 feat: add unified IM access policies 2026-09-01 10:46:41 +08:00
evanfang0054
fb3d6750c3 test(feishu): cover card-action and watch-completion topic threading 2026-09-01 10:02:11 +08:00
evanfang0054
fd6e0af81b feat(feishu): thread command replies, cards, and approvals to the triggering message
Plain command replies (menu cards, session/workspace/watch lists, /new,
/status, /compact, /archived, model and preset commands) and Harness
approval prompts were sent as fresh messages keyed only by chat_id, so
in topic groups they landed in the group's default area instead of the
topic the conversation belongs to.

Deliver them as replies to the triggering message, mirroring how stream
answers already thread:

- #sendCard accepts { replyTo } and replies interactively, falling back
  to a plain card when the referenced message is gone
- command replies, status text, menu/session/workspace/watch cards,
  approval prompts and resolved-question notices all carry the
  triggering message id
- batch-input failure notices follow the same rule

- bridge.test.mjs: /new in a topic group must thread the confirmation
  text and the menu card to the command message
- lib/index.js: regenerated host bundle
2026-08-31 20:06:04 +08:00
evanfang0054
3b810fea6b fix(feishu): present Harness questions as threaded replies in topic groups
Regular answers reuse the stream card, which is created through the
reply API targeting the triggering message, so they land in the right
Feishu thread. Pending Harness questions (ask_user_question) were sent
through a fresh message.create with only the chat_id, so in topic
groups they appeared in the group's default area instead of the topic
the conversation belongs to.

Thread question delivery the same way as answers:

- #send accepts { replyTo } and uses im.v1.message.reply, falling back
  to a plain message when the referenced one is gone
- the triggering message id now travels into the interaction context
  and pending state, and #presentInteraction replies to it
- resolved-question notices reply to the user's answer message

- bridge.test.mjs: assert the question is delivered via the reply API
  targeting the triggering message inside a topic group
- lib/index.js: regenerated host bundle
2026-08-31 17:12:55 +08:00
MikhailB
98c1e48271 feat: add session and preset list aliases 2026-08-30 02:34:40 +03:00
xmanrui
6c6d4af936 fix(feishu): preserve long streaming replies
Keep a bounded streaming preview, then deliver the complete final answer across multiple cards. Preserve all provider message IDs and cover long snapshots and Unicode boundaries with regression tests.

Fixes #78
2026-08-28 10:50:35 +08:00
xmanrui
1ce8126edb feat(settings): move IM bot to top-level menu
Remove the legacy Plugins-tab registrations, keep the channel-logo navigation, and harden upgrade/package verification.
2026-08-25 22:42:41 +08:00
Evilh2019
adeab2dec8
fix(feishu): treat single-text-paragraph posts as commands (#57)
Treat attachment-free Feishu rich-text posts containing bot commands like ordinary text commands instead of forwarding them to the Harness.

Co-authored-by: OpenClaw Agent <agent@openclaw.ai>
2026-08-25 19:28:20 +08:00
xmanrui
da01e3acee feat: add status reactions across messaging channels 2026-08-25 17:12:28 +08:00
xmanrui
7cbed3aefb fix: surface actionable channel message errors 2026-08-25 14:54:50 +08:00
xmanrui
c5becbe379 feat: add plugin version command 2026-08-25 12:25:01 +08:00
xmanrui
10ca7eec2c fix(feishu): complete permissions repair flow 2026-08-25 04:25:21 +08:00
xmanrui
068cf57259 feat: add private chat batch input commands 2026-08-25 02:39:31 +08:00
xmanrui
9e39333ff6 feat: add reasoning effort commands 2026-08-25 00:41:44 +08:00
xmanrui
bd9c58cf9e fix(feishu): stabilize post-merge card workflows 2026-08-24 18:49:32 +08:00
xmanrui
9d1dc71794 fix(feishu): harden interactive card flows 2026-08-24 18:49:32 +08:00
C3H3-AI
45f55f73eb fix(feishu): streamline menu card layout and update help card
- Move preset/model/archive controls from settings card to main menu
- Arrange 4 dropdowns in 2x2 grid with external icons
- Align steer and archive side by side
- Replace #showSettingsCard with #sendMenuCard for preset/model/archive updates
- Add #sendMenuCard after 'new' button action for consistency
- Update help card to reflect current menu layout (12 items)
- Clean up duplicate sessionlist entries in menuHelpText
- Add missing English dictionary entries
2026-08-24 09:46:32 +08:00
C3H3-AI
044ab74c28 merge: integrate upstream v2.0.0 (files, images, i18n) into feishu-card-system
- Resolve conflicts in feishu-cards.mjs / bridge.mjs / control-command.mjs / lib
- Keep card-system enhancements: menuCard/settingsCard/presetCard/modelCard, /m newCard, card form submit, model select
- Adopt upstream i18n t() wrapping + file/image delivery + inbound files
- Add missing English dictionary entries for new feishu card strings
- Rebuild lib (package now 2.0.0)
2026-08-24 07:22:50 +08:00
xmanrui
3ec5f1eca7 feat: add native image delivery across channels 2026-08-24 03:25:38 +08:00
xmanrui
0a26d7df92 feat: support inbound files across all channels 2026-08-23 22:39:26 +08:00
xmanrui
d472dd5a75 feat: add native result-file delivery 2026-08-23 20:02:06 +08:00
C3H3-AI
7a6e84cb89 fix(feishu): align menu number-fallback test with emoji label and bind-flows
The menu card renders the repair fallback as **5**<emoji>修复, so the two assertions that matched **5**修复 are broadened to tolerate the marker emoji. The number-reply on a later session page now reads the last text confirmation instead of assuming the last outgoing message is text, since #bindSession refreshes the menu card after binding. Rebuild bundle.
2026-08-23 09:41:38 +08:00
C3H3-AI
0241a32ec5 fix(feishu): conform card form submission and model select to upstream
- read form data from action.form_value (Card 2.0) instead of formValue

- wrap custom steer input and submit in a form container with submit button

- reuse runModelCommand for dropdown model picks so IDs with multiple / keep working

- pass key when sending the help card so back-to-menu stays valid

- compute initial_index from {value} option arrays

- add in-flight tests for menu stop, steer dropdown, and steer form
2026-08-23 07:11:17 +08:00
xmanrui
eea29fe296 feat: add agent preset chat commands 2026-08-22 04:04:44 +08:00
xmanrui
9950261a49 feat(feishu): add configurable group response mode 2026-08-22 01:26:29 +08:00
xmanrui
a199c65356 fix(feishu): make watch completion delivery reliable 2026-08-21 16:29:45 +08:00
liuwenbo00
4e325c62e0 feat(feishu): session-list rows as V2 column pairs (fixed star toggle + session button)
Each session row is a column_set with a fixed 90px watch-toggle column
(⭐关注/⭐取关 for already-watched sessions) and a weighted session button
carrying the number label; number replies bind the session. Replaces the
stacked button pair; also honors the per-bot archived-session policy.
2026-08-21 16:04:22 +08:00
liuwenbo00
10fd429852 feat(feishu): hide archived sessions by default (/archived on to reveal) 2026-08-21 16:02:32 +08:00
liuwenbo00
961dd5503d feat(feishu): /archived on|off toggle for archived sessions in lists
The session list (and the numeric /watch index) honors a per-bot persisted
policy: /archived off hides archived sessions from cards and index
resolution, /archived on restores them. Defaults to on.
2026-08-21 16:02:14 +08:00
liuwenbo00
beb269dc0e feat(feishu): persistent session watches and completion pushes
- /watch resolves the target READ-ONLY: sessions are validated against
  registered workspace listings (current or any other) without binding the
  conversation or switching workspaces. /unwatch and /watchlist round out
  the command set; the watchlist card supports button and number-reply
  unwatching.
- Watches persist in the state store (sessionId + title + chatId + lastSeq)
  and resume at runtime start: the bridge starts the global event-mux
  watcher in its constructor when the harness supports it.
- Completion pushes fire on turn/end, deduped by sessionId + turn id, with
  the seq watermark persisted per watch. After a mux reconnect the bridge
  replays each watched session's recent history (session.history) through
  the normal handler, so missed turn/end events are compensated without
  duplicates.
- Bound-session push targets are persisted (chatTargets) instead of living
  only in memory, and refresh on every accepted message.
- Watch failures map to safe user-facing messages.
2026-08-21 16:01:33 +08:00
xmanrui
c1a3b0cf97 fix(feishu): add one-click card callback repair 2026-08-21 13:43:02 +08:00
xmanrui
0e62c69382 fix(feishu): make interactive card menus reliable 2026-08-21 11:27:33 +08:00
liuwenbo00
6366404c42 feat(feishu): interactive card menus and session/workspace list cards
- /m (or /menu) opens a card menu; /sessionlist and /workspacelist render
  cards with bind/switch buttons; number replies stay usable as a fallback
  when the app does not subscribe card.action.trigger.
- card.action.trigger callbacks validate the operator's open_id against the
  allowed senders: group members outside the allowlist can never drive
  binding, workspace switches or other card actions.
- Session-list pagination uses page numbers everywhere (buttons carry
  sessions:<page>), fixing the previous double page-size scaling that
  skipped pages past 20 sessions.
- Bind/workspace failures map to safe user-facing messages instead of raw
  error details.
- Apps registered after this change subscribe card.action.trigger during
  the scan flow.
2026-08-21 10:03:23 +08:00
xmanrui
8121557460 feat: support numbered model selection 2026-08-20 03:11:20 +08:00
xmanrui
99ce38e9a4 feat: add model and turn control commands 2026-08-20 01:28:51 +08:00
xmanrui
3ac70a7c65 fix: remember direct recipients for connection tests 2026-08-19 11:24:50 +08:00
xmanrui
26558e5e71 fix: explain missing Feishu image permission 2026-08-19 03:13:11 +08:00
xmanrui
65c842c045 feat: support image prompts across IM channels 2026-08-19 02:56:14 +08:00
xmanrui
1cc7a26f30 feat: support compact command across IM channels 2026-08-18 23:20:05 +08:00
xmanrui
66bdad6299 fix: support Harness approvals across IM channels 2026-08-18 16:45:25 +08:00