Commit graph

68 commits

Author SHA1 Message Date
evanfang0054
bf03b7e696 feat(feishu): add stream card rotation to keep answers below mid-turn interactions 2026-09-01 17:53:42 +08:00
xmanrui
959e5b9ad2 fix(feishu): document numbered workspace switching 2026-09-01 15:47:27 +08:00
yusuke8h
91f49a603b fix: [Feature] 支持使用 /workspacelist 序号切换工作区 (#87) 2026-09-01 12:29:05 +09:00
xmanrui
840e5aa857 feat: add unified IM access policies 2026-09-01 10:46:41 +08:00
evanfang0054
82e7127cb4 fix(feishu): thread failure and error notices to the triggering message
Failure notices (turn failures, sub-flow errors from list/card/preset/
model/compact/stop/bind/switch paths, batch-input results, and the
card-queue rate-limit notice) 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 interaction belongs to.

- #sendFailure accepts options.replyTo; every call site forwards the
  anchor available in its context (command message, card message, or
  watch/list anchor)
- #handleMessageFailure and #finishBatchResult thread to the triggering
  message
- /repair stays private-chat-only by design; proactive delivery keeps
  its existing behavior (no thread context exists there)

- lib/index.js: regenerated host bundle
2026-09-01 10:02:11 +08:00
evanfang0054
6d815e0254 fix(feishu): deliver watch completions as replies inside the watch's topic
Watch-completion pushes rebuilt a fresh completion card keyed only by
chat_id, so in topic groups the "task finished" notice landed in the
group's default area instead of the topic where the watch was created.

- #runWatch persists the anchor message id (command message or card)
  on the durable watch entry
- #deliverCompletion sends the completion card as a reply to that
  anchor; entries without an anchor keep the previous behavior
- batch watch_add passes the card message as the anchor

- lib/index.js: regenerated host bundle
2026-09-01 10:02:11 +08:00
evanfang0054
fdab438a93 fix(feishu): thread card-action confirmations to the card message
Card-button sub-flows (bind session, watch/unwatch, workspace switch,
compact, stop, steer, preset/model selection and their confirmations)
sent fresh messages keyed only by chat_id, so in topic groups the
confirmations landed in the group's default area instead of the topic
containing the card.

- #handleCardAction anchors every confirmation and sub-flow to the
  card's message id; #handleMenuPick anchors to the replying message
- #bindSession / #switchWorkspace / #handleCompact / #handleStop /
  #handlePreset* / #handleModelSelect / #sendSteer accept and forward
  the anchor; the expired-menu and steer-form notices follow suit
- lib/index.js: regenerated host bundle
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
evanfang0054
da4114dfe3 feat(feishu): isolate Harness sessions per topic in topic groups
conversationKey derived the group session key from chat_id alone, so in
Feishu topic groups every topic shared one Harness session: context,
/new, pending approvals, and batch-input state all leaked across topics.

Append the event's thread_id to the session key when present. Topic
groups stamp every message with a thread_id, so each topic now maps to
its own group:<chat_id>🧵<thread_id> session. Regular group chats
carry no thread_id and keep the single shared group:<chat_id> key; p2p
keys are untouched.

- message-utils.mjs: thread-aware conversationKey
- message-utils.test.mjs: topic isolation + regular-group fallback cases
- lib/index.js: regenerated host bundle
2026-08-31 13:54:35 +08:00
xmanrui
347acceffb fix(feishu): integrate slash command permissions 2026-08-31 01:21:38 +08:00
C3H3-AI
64ba1463a8 feat(feishu): register native Slash Command panel on startup
The Feishu bot now calls the app_slash_commands OpenAPI at startup to register its common commands (menu, new, help, status, compact, sessionlist, workspacelist, watch, unwatch, watchlist, archived) as native Slash Commands, so typing / in a Feishu direct-message input box pops the command panel and tapping a command triggers it.

The command list is owned and pushed by dsh-im; it does not depend on the dsh/Harness backend. Registration is best-effort and runs asynchronously, so it never blocks the long-connection startup or message delivery when the app lacks the application:app_slash_command:read/write scopes.

Adds src/channels/feishu/slash-command-registry.mjs (manifest, list/create/delete, idempotent sync), wires it into feishu-runtime.mjs (slashCommands config flag + status fields), and covers it with tests.
2026-08-30 23:40:59 +08:00
xmanrui
31792d7bc8 feat: add stable proactive delivery 2026-08-30 11:24:53 +08:00
MikhailB
98c1e48271 feat: add session and preset list aliases 2026-08-30 02:34:40 +03:00
xmanrui
0cb79f74e9 feat: add message source context enhancement 2026-08-29 10:46:06 +08: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
8c6c31a1b6 feat: add bounded history previews across nine channels
Add shared /history parsing, read-only session access, message filtering, and bounded replies. Default to three messages, cap at five, and exclude saved history commands.

Include channel integration tests, translations, command help, and the Issue #62 implementation plan.
2026-08-28 03:01:53 +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
Zaakir
dcd7cd64d8 feat(i18n): add English support for host-side chat messages
Wrap all user-facing chat text in src/channels with a host-side t()
translator (Chinese is the identity default, so untranslated text is
always sent verbatim in Chinese). English is selected via the host
plugin config `language: en` or the DSH_IM_LANGUAGE environment
variable, and the settings UI keeps following the DSH web locale.

- add src/channels/shared/i18n.mjs with setImHostLanguage/t() and a
  Chinese-key -> English dictionary split by area (shared + channels)
- complete the English dictionary for every t() key in src/channels,
  including the feishu channel (welcome/help, repair flow, interactive
  cards, watch flow) and the shared command/approval/stream text
- wrap previously untranslated chat-facing strings in feishu bridge,
  feishu runtime, editable-message-stream, harness-client,
  connection-test and image-prompt
- dedupe dictionary entries that existed in multiple channel files and
  canonicalize conflicting translations into the shared dictionaries
- extend the i18n unit test to decode string-literal escapes so keys
  containing \n are checked correctly
- document the language switch in README.md, README.en.md and
  CHANGELOG.md, and rebuild lib/index.js

Added English support for bot chat messages across all nine IM
channels and AI Office without changing any Chinese output.
2026-08-24 00:32:30 +05: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
caa9e5eec2 fix(feishu): ensure /m sends a new card while other actions keep in-place updates 2026-08-23 11:13:03 +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
C3H3-AI
7d2c93da86 feat(feishu): expand menu card buttons and keep repair number-only
Add stop/compact/settings/watchlist buttons to the hub menu card, route repair through the numeric fallback (reply 6) without an extra button, and sync the menu help and card-structure test assertions. Rebuild the lib bundle so the published artifact carries the changes.
2026-08-23 06:16:26 +08:00
C3H3-AI
cf90ad95c3 feat(feishu): redesign interactive menu with dropdowns, settings panel, and steer input
Replace the flat button-only command menu with an information-architected
assistant center: status summary header, session dropdown (current session
pre-selected), workspace/model/preset dropdowns with current value shown,
archive toggle, task control (stop/compact/steer), watch multi-select, and a
collapsed settings panel. All commands expose card or dropdown entry points.
2026-08-22 21:52:31 +08:00
xmanrui
f7d2fe7047 fix(feishu): honor proxy settings for REST and WebSocket 2026-08-22 14:45:25 +08:00
xmanrui
eea29fe296 feat: add agent preset chat commands 2026-08-22 04:04:44 +08:00
xmanrui
7bf12628ce feat(feishu): add group message permission authorization 2026-08-22 02:29:59 +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
1790ec21ac feat(feishu): watchlist entry in the menu card 2026-08-21 16:04:00 +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
5055ffe6c8 feat(feishu): watch button on session-list cards, archived badge 2026-08-21 16:01:55 +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