Skip to content

feat(im): wire Feishu /project channel switching - #3708

Open
lengjingxu wants to merge 3 commits into
makecindy:mainfrom
lengjingxu:cindy/feishu-project-switching
Open

feat(im): wire Feishu /project channel switching#3708
lengjingxu wants to merge 3 commits into
makecindy:mainfrom
lengjingxu:cindy/feishu-project-switching

Conversation

@lengjingxu

@lengjingxu lengjingxu commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

What

Wire Feishu channel /project command by setting projectSwitching: true and providing the cards.project UI text pack in the Feishu adapter.

Fix: reject stale group-card /project switches when lane mapping is lost (app restart) — fail closed like existing /ctr control actions.

Why

Resolves the Feishu side of #3704 — the shared /project slash command and card action handler are already in place, but the Feishu adapter had not opted in. This commit enables it with the required Chinese UI copy.

Greptile flagged that a stale group card callback could fall back to the operator open_id and switch the DM session instead of the topic lane. Fixed in 229d0d8 by adding the same isGroupCardWithLostLane guard used by control actions.

Changes (2 commits, 5 files, +118)

feat(im): wire Feishu /project channel switching (4b7845e)

  • apps/desktop/src/main/im/feishu/adapter.ts — set projectSwitching: true
  • apps/desktop/src/main/im/feishu/uiText.ts — add cards.project text pack
  • apps/desktop/src/main/im/feishu/__tests__/feishuAdapter.test.ts — 3 tests (flag on, text shape, lane isolation)

fix(im): reject stale group-card /project switches when lane is lost (229d0d8)

  • apps/desktop/src/main/im/shared/cardActionHandler.tsisGroupCardWithLostLane guard on project:switch path; rejectStaleGroupCard accepts optional body
  • apps/desktop/src/main/im/shared/types.tscards.project.staleGroupCard optional field
  • apps/desktop/src/main/im/feishu/uiText.ts — staleGroupCard copy
  • apps/desktop/src/main/im/shared/__tests__/cardActionGroupLaneGuard.test.ts — 3 tests (pick fail-closed, dialogue fail-closed, topic lane not falsely blocked)

Verification

  • npx vitest run src/main/im — 62 files / 664 tests all pass
  • pnpm --filter desktop typecheck — 0 errors
  • pnpm check:dco — 2 commits signed
  • Live Feishu E2E (requires real bot connection; covered at contract layer by tests)

Dash checklist coverage

# Item Status
1 DM /project shows project list ✅ shared listProjectsForControl() + buildProjectPickerCard
2 Group/topic /project scoped to lane ✅ lane-isolated sessionId test
3 Two topics → different projects independently ✅ different lane → different session row
4 Old SDK context cleared on switch ✅ shared switchSessionWorkingDir clears + disposeOneSession
5 Back-to-dialogue uses managed dir ✅ shared project:dialogue path
6 Model/effort/provider/permission preserved ✅ shared switchSessionWorkingDir only touches workingDir + workspaceKind
7 Missing/file directory fails closed ✅ shared fs.statSync().isDirectory() guard
8 Stale/duplicate card clicks ✅ shared project:cancel + attachedUnsupported fallback
9 Stale group card lane loss → fail closed isGroupCardWithLostLane guard (same as /ctr)

Notes

Related: #3704
Depends on: #2624 (soft — no merge conflict on main today)

Signed-off-by: Leng <Lengjingxu@gmail.com>
@lengjingxu
lengjingxu requested a review from a team as a code owner September 1, 2026 03:24
@greptile-apps

greptile-apps Bot commented Sep 1, 2026

Copy link
Copy Markdown

Greptile Summary

This PR enables the shared /project workflow for Feishu and adds the corresponding Chinese card copy and adapter contract tests.

  • Enables projectSwitching in the Feishu adapter.
  • Adds the complete cards.project UI text pack.
  • Adds capability, text-shape, and lane-ID isolation tests.
  • The newly reachable card-action path does not reject group/topic callbacks after their in-memory lane mapping is lost.

Confidence Score: 4/5

The PR should not merge until stale Feishu group/topic project-card actions are prevented from switching the operator’s DM session.

Enabling project switching makes a wrong-session update reachable when a card callback outlives its in-memory lane mapping; the handler treats the operator open_id as the target identity instead of failing closed.

Files Needing Attention: apps/desktop/src/main/im/feishu/adapter.ts

Important Files Changed

Filename Overview
apps/desktop/src/main/im/feishu/adapter.ts Enables the project-switching flow, but thereby exposes project card actions to stale group/topic callbacks that can fall back to the DM session.
apps/desktop/src/main/im/feishu/uiText.ts Adds a complete Feishu project-card text pack matching the shared UI contract.
apps/desktop/src/main/im/feishu/tests/feishuAdapter.test.ts Covers capability wiring, text shape, and session-ID derivation, but not lane loss between card creation and callback handling.

Sequence Diagram

sequenceDiagram
    participant U as Feishu user
    participant F as Feishu transport
    participant L as Lane registry
    participant H as Project action handler
    participant S as Session repository
    U->>F: Click old project card
    F->>L: Resolve card messageId
    L-->>F: No lane after restart/eviction
    F->>H: "senderId = operator open_id"
    H->>S: Resolve route as DM session
    H->>S: Switch DM working directory
    H-->>U: Patch card as successful
Loading
Prompt To Fix All With AI
### Issue 1
apps/desktop/src/main/im/feishu/adapter.ts:335
**旧卡片切错会话**

当桌面进程重启、Feishu 客户端重新绑定或 lane 缓存淘汰后,群聊或话题中的旧 `/project` 卡片无法恢复原 lane,回调会保留操作者的 `open_id` 并按私聊身份解析目标,导致项目操作切换私聊会话而非卡片所在的话题会话,同时卡片仍会显示切换成功。项目动作需要像现有 control 动作一样在群卡 lane 丢失时拒绝执行。

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "feat(im): wire Feishu /project channel s..." | Re-trigger Greptile

Comment thread apps/desktop/src/main/im/feishu/adapter.ts
@MagicLizi

Copy link
Copy Markdown
Contributor

@lengjingxu 👋 这个 PR 还有 1 条 review conversation 没 resolve(apps/desktop/src/main/im/feishu/adapter.ts),auto-review 因此暂时跳过、没法继续审查 / 合并。

如果你已经按评论改完或回应了,请到对应 thread 上点 Resolve conversation;全部 resolve 后,下一轮 auto-review 会自动重新审查这个 PR。

@MagicLizi MagicLizi added awaiting-discussion 等待维护者讨论(review-pr) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示) labels Sep 1, 2026
Signed-off-by: Leng <Lengjingxu@gmail.com>
@MagicLizi

Copy link
Copy Markdown
Contributor

这个 PR 会让飞书 /project 真正切换频道,已进入维护者确认,球不在作者手里。

请维护者直接在 PR 上 Approve;需要修改就 Request Changes。讨论 issue:#3719

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

Labels

awaiting-discussion 等待维护者讨论(review-pr) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants