Commit graph

409 commits

Author SHA1 Message Date
xmanrui
c7679d86a1 Merge pull request #118 from GoldJohnKing/fix/non-vision-model-image-file-fallback 2026-09-02 01:33:28 +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
C3H3-AI
955c2217fd fix(feishu): renew the reply wait window while the turn is active
A long-running Harness task was falsely reported as MODEL_REPLY_TIMEOUT
after the fixed 10-minute deadline even though the backend was still
working. Replace the hard wall-clock deadline with an activity-based
stall window: the wait renews whenever the turn produces new events, the
control ownership is active, or (mid-turn with no new events) Harness
still reports the session as running. Only a genuine stall with no
progress for the whole timeoutMs window fails fast.

This is the shared harness-client layer, exercised end-to-end by the
Feishu channel (which already exposes HARNESS_REPLY_TIMEOUT_MS); other
channels inherit the same fix.

Adds two regression tests: a long-running turn with periodic activity
completes instead of timing out, and a genuinely stalled turn still
fails with harness-reply-timeout.
2026-09-02 00:17:18 +08:00
GoldJohnKing
994df6e1e3 Merge upstream v4.5.0 (xmanrui/main) into fix/non-vision-model-image-file-fallback
- CHANGELOG: keep the image-fallback entry under Unreleased alongside the new 4.5.0 section
- harness-client: upstream renameSession coexists with the image-rejection fallback retry path
- lib/index.js rebuilt from merged sources
2026-09-01 23:18:12 +08:00
xmanrui
c2be2389b0 chore: release v4.5.0 2026-09-01 22:39:47 +08:00
xmanrui
d044f1b0aa fix: preserve session titles without context enhancement 2026-09-01 22:30:35 +08:00
GoldJohnKing
36d10dc499 chore: rebuild lib for non-vision image fallback 2026-09-01 21:29:43 +08:00
GoldJohnKing
0851e8cf30 fix(im): fall back to workspace-file delivery when non-vision models reject images 2026-09-01 21:29:43 +08:00
Evan Fang
e8c9817598
Merge pull request #108 from xmanrui/fix/issue-86-feishu-stream-order
fix(feishu): rotate the streaming card before in-turn interactions (issue #86)
2026-09-01 17:56:04 +08:00
evanfang0054
c7cb678bd2 chore: rebuild lib for feishu issue-86 card rotation 2026-09-01 17:53:44 +08:00
evanfang0054
1a165822ac fix(feishu): rotate the streaming card before presenting in-turn interactions 2026-09-01 17:53:42 +08:00
evanfang0054
bf03b7e696 feat(feishu): add stream card rotation to keep answers below mid-turn interactions 2026-09-01 17:53:42 +08:00
xiemanR
24f4a1e05b
Merge pull request #109 from yzxxy010/feat/conversation-title
上下文增强增加 conversationTitle 字段
2026-09-01 17:24:47 +08:00
xmanrui
fd303b6c78 Merge main into feat/conversation-title 2026-09-01 17:22:49 +08:00
曜 星
7a68e94f54 feat: add conversationTitle to context enhancement
Pass inbound group titles into <dsh_im_source> without extra platform API lookups.
DingTalk uses conversationTitle; Telegram groups use chat.title.
2026-09-01 17:15:17 +08:00
xmanrui
9c4628a821 build: refresh host bundle after workspace updates 2026-09-01 16:29:20 +08:00
yusuke8h
65c1c55f1a fix: [Feature] 为工作区命令增加 /ws、/wsl 和 /workspaces 别名 (#88) 2026-09-01 17:03:48 +09:00
xmanrui
959e5b9ad2 fix(feishu): document numbered workspace switching 2026-09-01 15:47:27 +08:00
xiemanR
61c353a4cb
Merge pull request #110 from yhay81/agent/issue-87
fix: 支持使用 /workspacelist 序号切换工作区
2026-09-01 15:43:43 +08:00
xmanrui
13fc85cdce chore: release v4.4.0 2026-09-01 12:33:36 +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
Evan Fang
075d2713c1
Merge pull request #104 from evanfang0054/fix/feishu-thread-card-actions
fix(feishu): thread card-action confirmations to the card message
2026-09-01 10:05:40 +08:00
evanfang0054
fb3d6750c3 test(feishu): cover card-action and watch-completion topic threading 2026-09-01 10:02:11 +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
Evan Fang
165def416a
Merge pull request #103 from evanfang0054/fix/feishu-ws-honor-no-proxy
fix(feishu): honor NO_PROXY before proxying the long connection
2026-09-01 10:01:28 +08:00
evanfang0054
adc0a89f13 fix(feishu): honor NO_PROXY before proxying the long connection
webSocketProxyUrl() picks up https_proxy/HTTPS_PROXY/http_proxy/
HTTP_PROXY and forces the Feishu WSS long connection through the proxy,
without consulting NO_PROXY/no_proxy. With a local proxy exported in
the shell (Clash/V2Ray setups), every long-connection attempt is
rejected by Feishu's server and the runtime force-closes and retries
in a loop, so the bot never reaches a stable connected state.

Resolve NO_PROXY/no_proxy for the long-connection endpoints
(open.feishu.cn / open.larksuite.com) before falling back to the proxy
env: exact host, parent-domain (.cn, feishu.cn) and * entries follow
the common NO_PROXY semantics.

- production.mjs: NO_PROXY gate in front of the proxy lookup
- feishu-proxy.test.mjs: NO_PROXY exclusion and fallthrough cases
- lib/index.js: regenerated host bundle
2026-09-01 09:46:49 +08:00
xmanrui
009f1abec9 feat: add tabs to bot settings 2026-09-01 02:31:57 +08:00
xmanrui
08368c135c chore: release v4.3.0 2026-09-01 02:09:33 +08:00
xmanrui
75ebaebf2e feat: split group and direct context enhancement 2026-09-01 02:06:22 +08:00
xmanrui
38096d1589 test: wait for update service shutdown before restart 2026-08-31 20:30:48 +08:00
xiemanR
7a16718922
Merge pull request #101 from evanfang0054/feat/feishu-topic-session-isolation
feat(feishu): isolate Harness sessions per topic in topic groups
2026-08-31 20:08:45 +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
xmanrui
1ce922933f update docs 2026-08-31 16:28:09 +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
xiemanR
5ac63dd26b
Merge pull request #97 from Diluka/feat/qq-parse-face-tags
feat(qq): parse inbound QQ face/emoji tags into readable text
2026-08-31 10:02:46 +08:00
Diluka
5efcfa6725 feat(qq): parse inbound QQ face/emoji tags into readable text
QQ delivers emoji messages as opaque <faceType=..,faceId="..",ext="..">
markup fragments (the ext field holds a base64 JSON blob with the face
name, e.g. {"text":"吃瓜"}). Without translation, the Harness receives
only this unusable tag and loses what the sender actually meant.

Register the SDK's contentSanitizer({ parseFaceTags: true }) middleware,
mirroring tencent-connect/dsh-qqbot, so C2C and group inbound messages
surface as e.g. 【表情: 吃瓜】 instead of the raw tag.

- qq-runtime.mjs: register contentSanitizer before the typing indicator
- runtime.test.mjs: assert sanitizer registration and update middleware order
- lib/index.js: regenerated host bundle
2026-08-31 09:07:55 +08:00
xmanrui
a0845a7a25 chore: release v4.2.1 2026-08-31 03:33:15 +08:00
xmanrui
14519060f0 fix(telegram): isolate long polling transport 2026-08-31 03:31:07 +08:00
xmanrui
02ddea0054 chore: release v4.2.0 2026-08-31 01:38:31 +08:00
xiemanR
15c6bd2a45
Merge pull request #94 from C3H3-AI/feat/feishu-slash-commands
feat(feishu): 启动时注册飞书原生 Slash Command 命令面板
2026-08-31 01:22:08 +08:00
xmanrui
347acceffb fix(feishu): integrate slash command permissions 2026-08-31 01:21:38 +08:00
xmanrui
29aa138b3b Merge remote-tracking branch 'origin/main' into codex/pr94-updated
# Conflicts:
#	CHANGELOG.md
2026-08-31 01:21:34 +08:00
xmanrui
4496c9601e chore: release v4.1.1 2026-08-31 00:50:07 +08:00
xmanrui
4d18cc4de0 fix(qq): respond to all mentioned group members 2026-08-31 00:45:59 +08:00