Skip to content

feat(desktop): 接线 X (Twitter) hook provider - #1230

Merged
MagicLizi merged 3 commits into
mainfrom
dash/x-provider-client
Jul 31, 2026
Merged

feat(desktop): 接线 X (Twitter) hook provider#1230
MagicLizi merged 3 commits into
mainfrom
dash/x-provider-client

Conversation

@dashhuang

Copy link
Copy Markdown
Member

这次改了什么

摘要

X (Twitter) 机器人链路的第 4 步:desktop 客户端接线 x hook provider。用户在设置页「IM 机器人 · 官方」栏可开启 X 渠道、完成 X 账号 OAuth 绑定,之后在 X 上 @提及 Cindy bot 即可向本机派发任务(服务端 x-hook-server 已随 xindong/cindy-server#211 合入,产品调研与实施顺序见 #691)。X 走与 Telegram 相同的 provider-neutral 状态机(#695 泛化重构的表驱动 lane),本 PR 的主体是「追加一行 lane 配置 + 打通若干 Telegram 写死的洞」,并顺手把这些洞参数化,第三个 provider 不用再踩一遍。

要点:

  • 协议:cindy-protocol 指针 bump 至主干 2520a40(含 'x' provider 常量与 provider:x 能力旗标)。服务端 x-hook-server 已消费同源常量;指针相对 main 此前的 a9a34e6 多出的 turn.reopen 帧走能力协商,desktop 不宣告即不参与,无兼容影响。main 侧同学在 a9a34e6 bump 时预留的「X 落地时放宽 ClientHookProvider」口子,本 PR 按其预期落位。
  • hook-control:新增 xConfig lane;providerForTaskDispatch / providerForExternalKey 增加 x: 前缀路由,source/key 错配 fail-closed;参数化三处 Telegram 写死点——openProviderAction(provider, action)、六个 provider-neutral IPC handler 从 payload 取 provider、connectionId 后缀解析不再二分兜底(未登记 provider 不得读到 Slack 的开关与端点)。
  • 安全边界:新增 xDeepLink.ts——X OAuth2 (PKCE) 授权 URL 的精确校验(https + 精确 host/path + 参数键集恰好匹配 + S256,拒凭证/端口/fragment/重复与未知参数),与 t.me 校验彼此独立不复用;bot profile URL 仅接受裸 handle。
  • store 与偏好:xEnabled / xBindingCache 账号分区槽位;setProviderBindingCache 泛化;workspaceProviderSourceStore 的 persist 白名单补 'x'(新增用例先行抓到:缺了会让 x 的目录级模型来源偏好静默失效)。
  • 绑定 UI:x 渠道卡与 Telegram 卡同构渲染(提炼 renderProviderCard,动作按钮完全由 binding.actions 数据驱动——X 无加群概念,add_to_group 不下发即不渲染);HookWorkspacePrefsEditor 泛化为 neutral provider 语义(x prefs 按 bindingId 归属)。
  • 会话链路:sessions.source 支持 'x'(SQLite 该列无 CHECK 约束,drizzle enum 仅类型层,零 migration)并进侧边栏可见集;X 纯文本回帖的 prompt note;vendorOptions.source='x' 与 lizi-mcps NOTE_BY_SOURCE 的隐式契约两侧同补;任务卡 X 图标与标签;mobile 渲染/normalize 三处补 x。
  • 端点与灰度:clientEndpoints 新增 xHookWsUrl(wss: 白名单,纯增可选字段不 bump schemaVersion);仓内 config/endpoint*.json 刻意不加条目——清单缺失该 key 解析为空串,设置卡即不可见,这就是灰度/回滚开关,x-hook-server 部署后改 CDN 正本即可放量。
  • i18n:四语言 hook.x.* 整块 + providerX 显示名 + chat 描述补 X;Telegram 的 openTelegram key 更名 openApp 与 x 块结构平行。

变更类型

  • feat 新功能
  • fix 缺陷修复
  • refactor / perf 重构或性能优化
  • docs / test / chore 文档、测试或工程维护
  • 其他:

范围

  • 关联 Issue / 需求:feat: X (Twitter) 机器人渠道 —— @提及派发任务并读取 thread 上下文(调研结论与实施计划) #691(X 机器人计划);服务端对应 xindong/cindy-server#211
  • 本 PR 包含:desktop x provider 全链路接线(协议 bump、lane、绑定 UI、prefs、会话来源、i18n、mobile 渲染、端点 key)与配套测试
  • 明确不包含:x-hook-server 部署与端点清单放量(CDN 正本改动)、X 账号/OAuth app/XAA 等外部前置、AI reply 平台审批
  • 用户可见变化:端点清单未配置 xHookWsUrl无任何可见变化(x 卡隐藏);放量后设置页出现 X 渠道卡,绑定后 X 会话进侧边栏、任务卡带 X 图标
  • 是否存在 breaking change:无

UI 变化

设置页「IM 机器人 · 官方」栏新增 X 渠道卡,与 Telegram 卡同构(收起行 = 状态徽章 + 绑定摘要 + 开关;展开区 = 授权动作 + 工作目录映射);聊天任务卡新增 X 图标(XIcon,currentColor 随主题)。因端点未放量,当前构建不可见,未附截图;实机截图待部署后在放量 PR 里补。

  • 引用的设计规范:DESIGN.md §2 Color Palette & Roles(全部颜色走语义 token:状态徽章沿用 --settings-badge-*,文本 --text-secondary/tertiary、错误 --error-fg,无硬编码色,Light/Dark 双模式同源实现);§4 Component Stylings · Cards & Containers(复用 ImChannelSettingsCard 手风琴卡与既有 pill 按钮样式,未新增容器样式);§7 Do's and Don'ts(不引入新交互模式,动作按钮按服务端下发的 binding.actions 数据驱动)。双模式为同一 themed 实现,未实机目检(端点未放量,卡在当前环境不可见),按 DESIGN.md 双模式交付门槛如实登记。

怎么验证的

自动验证

bash run-unit-gate.sh(仓库根 pnpm test:unit 全量,rebase 到 origin/main bdbcffdc 后重跑)
结果:见 PR 检查区 CI;本地首轮除 makerSendToSessionOrdering 3 个基线预存失败外全绿
     (该失败在干净 origin/main 基线同样复现,其源码抽取目标本 PR 未触碰,与本 diff 无关)

pnpm --filter desktop exec tsc --noEmit
结果:0 错误

pnpm --filter desktop exec vitest run src/main/hook-control src/renderer/components/settings/__tests__ src/renderer/__tests__/automationGeneratedSessions.test.ts
结果:40 files / 585 tests 全部通过(rebase 后复跑,含 main 新合入的 BYO Telegram bot 等 hook 测试)

pnpm --filter mobile exec vitest run src/__tests__/hookSourceRendering.test.ts src/__tests__/messageNormalize.test.ts
结果:33 tests 通过

pnpm --filter @cindy/maker-shared exec vitest run src/__tests__/clientEndpoints.test.ts
结果:69 tests 通过

pnpm check:i18n-glossary
结果:en / zh-CN / ja / ko 无新增违规

新增测试:xDeepLink.test.ts(授权 URL 16 条负向用例 + profile URL);x 路由 source/key 错配 fail-closed;workspaceProviderSourceStore x 渠道隔离(先行抓到 persist 白名单洞);outbound X 平台名与纯文本格式约束;lizi-mcps x 渠道 note 契约;store x 槽位与账号分区;设置组件与 prefs fixture 补 x。

手工验证

不涉及:x-hook-server 尚未部署、端点未放量,本机无法端到端连通;UI 卡在端点为空时按设计隐藏(该隐藏行为由 HookConnectionsSection 可见性 gate 的既有测试覆盖)。

未执行的验证

风险

风险分类

  • 无已知风险
  • SQLite / migration
  • system prompt
  • 协议兼容
  • 权限 / 安全 / 用户数据
  • 原生层 / fingerprint / OTA
  • 跨平台差异
  • 其他:X OAuth 授权 URL 经系统浏览器打开(shell 边界)

影响与回滚

  • 影响范围:端点清单未配置 xHookWsUrl 时零行为变化(x lane 端点为空不建连、卡不可见);协议指针 bump 相对 main 仅前进一个 docs+帧定义 commit(turn.reopen),desktop 不宣告该能力,对现有 Slack/Telegram 连接无影响。sessions.source 枚举为纯增(无 SQL 约束),slack-hook.json 配置为纯增字段,旧版本读到多余字段自动忽略。
  • 回滚 / 降级方式:CDN 端点正本移除/清空 xHookWsUrl 即整体下线 x 渠道(卡隐藏、不建连),无需发版;代码回滚 revert 本 PR 即可,无持久化残留需要清理(xEnabled/xBindingCache 字段旧版本解析时按未知字段忽略)。
  • shell 边界:openXUrlshell.openExternal 前经 validateXExternalUrl 精确校验(host/path/参数集),与 Telegram 的 t.me 校验同级但独立,负向用例覆盖凭证/端口/fragment/参数走私。

提交前检查

  • 已 review 完整 diff
  • 每个 commit 都带 DCO 签名(git commit -s,见 DCO)
  • UI 改动已在「UI 变化」注明引用的设计规范章节(不涉及 UI 则跳过)
  • 未提交凭证、令牌或授权文件
  • 已补充必要文档
  • 已确认测试结果或说明未执行原因

@dashhuang
dashhuang requested a review from a team as a code owner July 31, 2026 14:05
Copilot AI review requested due to automatic review settings July 31, 2026 14:05
@greptile-apps

greptile-apps Bot commented Jul 31, 2026

Copy link
Copy Markdown

Greptile Summary

本次 PR 将 X(Twitter)接入桌面端现有的 provider-neutral Hook 链路。

  • 新增 X 连接、OAuth 绑定、目录偏好、任务派发与会话来源支持
  • 泛化 Telegram 专用的 IPC、状态机、设置卡和偏好编辑逻辑
  • 增加 X 外部链接校验、跨区端点缓存策略及桌面端和移动端展示
  • 补充 X 渠道路由、绑定操作、偏好隔离与深链安全测试

Confidence Score: 5/5

当前修复已覆盖此前反馈的问题,PR 看起来可以安全合并。

当前代码按 connectionId 的 provider 末段选择配置并拒绝未知值,同时允许 CN 构建缓存受信任的 cindy.app X Hook 端点;未发现仍然存在的阻断性故障。

Important Files Changed

Filename Overview
apps/desktop/src/main/hook-control/manager.ts 新增表驱动的 X provider lane,并扩展路由、能力协商、绑定、偏好和外部动作处理。
apps/desktop/src/main/hook-control/ipc.ts 将 provider IPC 泛化至 Telegram 与 X,并让连接标识解析对未知 provider 采取拒绝策略。
apps/desktop/src/main/hook-control/xDeepLink.ts 为 X OAuth 授权地址和账号主页地址增加独立的严格校验边界。
apps/desktop/src/main/endpointManifestCache.ts 将 X Hook 端点纳入跨区共享服务白名单,使 CN 构建可使用 Global 域的离线缓存端点。
apps/desktop/src/renderer/components/settings/HookConnectionsSection.tsx 提炼 provider-neutral 设置卡并接入 X 渠道的开关、绑定动作和工作目录配置。
apps/desktop/src/renderer/components/settings/HookWorkspacePrefsEditor.tsx 将渠道偏好读取、写入和推送隔离逻辑扩展至 X provider。

Sequence Diagram

sequenceDiagram
    participant U as 用户
    participant UI as Desktop 设置页
    participant Main as Hook Control
    participant X as X Hook Server
    participant Browser as 系统浏览器

    U->>UI: 开启 X 渠道
    UI->>Main: setProviderEnabled(x, true)
    Main->>X: WebSocket + JWT / hello(provider:x)
    X-->>Main: provider.bind.state
    U->>UI: 发起账号绑定
    UI->>Main: providerBindStart(x)
    Main->>X: provider.bind.start
    X-->>Main: pending + OAuth URL
    Main->>Browser: 校验后打开 X OAuth URL
    X-->>Main: confirmed binding
    Main-->>UI: 推送 X 连接与绑定状态
    X->>Main: "task.dispatch(source=x)"
    Main->>Main: 校验 source 与 x: externalKey 一致
    Main-->>X: task.ack / 任务结果
Loading

Reviews (3): Last reviewed commit: "test(desktop): 补 X 渠道设置卡与 prefs 路由镜像用例" | Re-trigger Greptile

Copilot AI 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.

Pull request overview

本 PR 在现有 Slack/Telegram hook-control provider-neutral 状态机基础上,为 Desktop 客户端接入第三个渠道 X (Twitter) hook provider,并同步补齐共享端点清单、会话来源枚举、渠道提示(note)与 Mobile 渲染,使 X 渠道可在端点清单放量后通过设置页完成 OAuth 绑定并参与任务派发/会话展示。

Changes:

  • 在 desktop hook-control 中新增 X lane 配置、provider 路由与 IPC 形状扩展(含 open action / prefs / binding cache / session source 等)。
  • 新增并接入 X OAuth2(PKCE) 授权链接与 profile 链接的严格校验(shell.openExternal 前的 main 边界校验),并补齐单测。
  • 扩展 maker-shared 端点清单键、lizi-mcps 渠道路由 note、i18n 与 mobile/desktop UI 渲染以展示 X 来源与图标。

Reviewed changes

Copilot reviewed 37 out of 38 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/maker-shared/src/clientEndpoints.ts 端点清单新增 xHookWsUrl key 与 wss: 协议白名单。
packages/maker-shared/src/tests/clientEndpoints.test.ts 端点清单解析用例补齐 xHookWsUrl
packages/lizi-mcps/src/cindy_feishuBotMcpServer.ts 增加 X 会话渠道 note,并纳入 NOTE_BY_SOURCE 路由契约。
packages/lizi-mcps/src/tests/feishuBotChannelRouting.test.ts 覆盖 X note 的路由拼接与不串扰断言。
apps/mobile/src/session/MessageRenderer.tsx hookSource 标题展示补 X(Telegram/X/Slack)。
apps/mobile/src/session/messageNormalize.ts hookSource.im 扩展为 slack/telegram/x 并 fail-closed 解析。
apps/mobile/src/tests/hookSourceRendering.test.ts 对应更新渲染字符串断言以覆盖 X。
apps/desktop/src/test/vitest/clientEndpointsFixture.ts desktop 端点 fixture 补 xHookWsUrl
apps/desktop/src/shared/sessionSource.ts desktop session source 白名单与 normalize 逻辑补 x
apps/desktop/src/shared/hookControlIpc.ts HookProvider/视图形状扩展:新增 x provider 字段与 provider-neutral 类型别名。
apps/desktop/src/renderer/vite-env.d.ts renderer 侧 ElectronAPI 类型扩展:provider 形参放宽至 `telegram
apps/desktop/src/renderer/i18n/locales/zh-CN/common.json 新增 hook.x.* 文案块、providerX 名称,并同步 Telegram key 结构对齐。
apps/desktop/src/renderer/i18n/locales/ko/common.json 同步新增/更新 X 与 Telegram 对应文案 key。
apps/desktop/src/renderer/i18n/locales/ja/common.json 同步新增/更新 X 与 Telegram 对应文案 key。
apps/desktop/src/renderer/i18n/locales/en/common.json 同步新增/更新 X 与 Telegram 对应文案 key。
apps/desktop/src/renderer/components/settings/HookWorkspacePrefsEditor.tsx provider-neutral prefs 读写泛化到 Telegram/X(按 bindingId 归属)。
apps/desktop/src/renderer/components/settings/HookConnectionsSection.tsx 设置页渠道卡抽象为 provider-neutral 渲染函数,并新增 X 卡。
apps/desktop/src/renderer/components/settings/tests/HookWorkspacePrefsEditor.test.tsx fixture 补 hook.x 视图字段以覆盖新形状。
apps/desktop/src/renderer/components/settings/tests/HookConnectionsSection.test.tsx IPC mock/断言从 Telegram 专属 open action 切到 provider-neutral open action,并更新 i18n key。
apps/desktop/src/renderer/components/chat/XIcon.tsx 新增 X 图标组件(currentColor)。
apps/desktop/src/renderer/components/chat/HookTaskCard.tsx 任务卡 IM 图标/标签补 X。
apps/desktop/src/renderer/tests/automationGeneratedSessions.test.ts desktop 可见会话 source 合同断言补 x
apps/desktop/src/preload/preload.ts preload API 调整为 provider-neutral IPC 形参(provider: telegram/x)。
apps/desktop/src/main/localDb/schema.ts 本地 DB session source 枚举补 x(类型层)。
apps/desktop/src/main/localDb/ipc/sessions.ts setSessionSourceInDb 放宽为 `telegram
apps/desktop/src/main/hook-control/xDeepLink.ts 新增 X OAuth2(PKCE) 授权 URL 与 profile URL 的严格校验实现。
apps/desktop/src/main/hook-control/workspaceProviderSourceStore.ts workspace provider source store 持久化白名单补 x
apps/desktop/src/main/hook-control/store.ts store 增加 xEnabled/xBindingCache 槽位并泛化 provider binding cache 写入接口。
apps/desktop/src/main/hook-control/session-runner.ts 会话创建链路补 vendorOptions.source='x' 与 session source 持久化。
apps/desktop/src/main/hook-control/outbound.ts prompt note 平台名与格式约束补 X(纯文本回帖提示)。
apps/desktop/src/main/hook-control/manager.ts 新增 xConfig lane,provider 路由/动作/prefs/binding cache/快照字段扩展到 X。
apps/desktop/src/main/hook-control/ipc.ts IPC handler 扩展到 provider-neutral(telegram/x)形参,并新增 shell.openExternal 的 X URL 校验。
apps/desktop/src/main/hook-control/dispatcher.ts 派发入参展示字段对 X 渠道按 Telegram 同口径取 channelName。
apps/desktop/src/main/hook-control/tests/xDeepLink.test.ts 新增 X URL 校验的正向/负向覆盖用例。
apps/desktop/src/main/hook-control/tests/workspaceProviderSourceStore.test.ts 覆盖 workspaceProviderSourceStore 的 X 渠道隔离与读写。
apps/desktop/src/main/hook-control/tests/transport-manager.test.ts hook-control 状态机测试扩展:store 槽位/边界路由/open action 改名适配等。
apps/desktop/src/main/hook-control/tests/store.test.ts store 默认态与账号隔离用例更新为 provider binding cache 泛化接口与 X 槽位。
apps/desktop/src/main/hook-control/tests/outbound.test.ts outbound prompt note 用例覆盖 X 平台名与纯文本约束。

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/desktop/src/main/hook-control/ipc.ts Outdated
Comment thread apps/desktop/src/main/hook-control/manager.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2d04e22fb6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/maker-shared/src/clientEndpoints.ts
X 机器人第 4 步(计划见 #691):desktop 侧接入独立部署的
x-hook-server,与 Telegram 同走 provider-neutral 状态机。

- 协议: cindy-protocol 指针 bump 至主干 2520a40(含 'x' provider 常量与
  provider:x 能力旗标;服务端 x-hook-server 已同步消费,新增的
  turn.reopen 等帧靠能力协商向后兼容,desktop 不宣告即不参与)。
- hook-control: 新增 x lane 配置(端点 xHookWsUrl、requiredFeatures 含
  provider:x、绑定缓存、OAuth 授权 URL 校验);顺手参数化三处 Telegram
  写死的洞 —— openProviderAction(provider, action)、IPC 六个
  provider-neutral handler 从 payload 取 provider、connectionId 后缀解析
  不再二分兜底(未登记 provider 不得落到 Slack 的开关与端点)。
  providerForTaskDispatch / providerForExternalKey 增加 x: 前缀路由,
  source/key 错配 fail-closed。
- 安全边界: 新增 xDeepLink.ts —— X OAuth2 (PKCE) 授权 URL 的精确校验
  (host/path/参数键集/S256, 拒凭证/端口/fragment/参数走私), 与 t.me
  校验彼此独立不复用; profile URL 仅接受裸 handle。
- store: xEnabled / xBindingCache 账号分区槽位, setProviderBindingCache
  泛化; workspaceProviderSourceStore 的 persist 白名单补 'x'(新用例先行
  抓到该洞: 缺了会让 x 的目录级来源偏好静默失效)。
- 绑定 UI: 设置页 x 渠道卡与 Telegram 卡同构渲染(renderProviderCard,
  动作按钮完全由 binding.actions 数据驱动, X 无加群按钮自然不渲染);
  HookWorkspacePrefsEditor 泛化为 neutral provider 语义(x prefs 按
  bindingId 归属)。端点清单刻意不加 xHookWsUrl 条目 —— 缺失解析为空串
  即卡不可见, 这就是灰度/回滚开关, 部署后改 CDN 正本即可。
- 会话链路: sessions.source 支持 'x'(SQLite 无 CHECK 约束, 零 migration)
  并进侧边栏可见集; X 纯文本回帖的 prompt note; vendorOptions.source='x'
  与 lizi-mcps NOTE_BY_SOURCE 的隐式契约两侧同补; 任务卡 X 图标与标签;
  mobile 渲染与 normalize 三处补 x。
- i18n: 四语言 hook.x.* 整块 + providerX + chat 描述; Telegram 的
  openTelegram key 更名 openApp(与 x 块结构平行)。

验证: desktop typecheck 0 错; 全量 test:unit 除 3 个基线预存失败
(makerSendToSessionOrdering, 于干净 main 基线同样复现, 与本 diff 无关,
其抽取的源文件本 PR 未触碰)外全绿; hook-control 345 / 设置组件 122 /
mobile 33 / clientEndpoints 69 全过; check:i18n-glossary 通过。
双模式复用既有 themed 组件与语义 token, 未实机目检(如实登记)。

Signed-off-by: Dash <dashhuang@gmail.com>
- ipc.ts getConnection: connectionId 末段解析 provider,未登记值返回
  null(dispatcher 按连接不存在拒绝,fail closed),不再兜底回落 Slack
- manager.ts: ProviderOpenAction 注释改用现名 openProviderAction
- endpointManifestCache: xHookWsUrl 登记进 CROSS_REGION_ENDPOINT_KEYS
  (x-hook 与 slack/telegram 同款跨区单部署),CN 清单合规测试补 X 端点,
  避免 CN 构建离线缓存回退把 X 端点判为不可信

Signed-off-by: Dash <dashhuang@gmail.com>

Copilot AI 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.

Pull request overview

Copilot reviewed 39 out of 40 changed files in this pull request and generated no new comments.

Suppressed comments (2)

apps/desktop/src/renderer/components/settings/tests/HookConnectionsSection.test.tsx:115

  • 这里新增了 X provider 字段与 provider-neutral 渲染分支,但本文件的用例仍只覆盖 Slack/Telegram。建议补充至少一条 X 卡用例,验证:当 x.url 已配置且 enabled/available 时卡可见;pending/confirmed 状态下按钮按 actions 渲染;点击“openApp/openBot”等动作会调用 openProviderAction('x', );且 X 不应渲染 add-to-group 按钮(除非 actions 明确包含)。否则 X 卡逻辑回归很难被现有测试捕捉。
  x: {
    enabled: false,
    url: '',
    status: 'disabled',
    lastError: null,

apps/desktop/src/renderer/components/settings/tests/HookWorkspacePrefsEditor.test.tsx:45

  • useHookWorkspacePrefs 已泛化为 neutral provider(Telegram / X)并通过 IPC 传 provider 参数、用 ${provider}:${bindingId} 做 ready identity,但本测试集目前只覆盖 Telegram 的 provider prefs 流。建议补充 X 的镜像用例(例如 X 已连接且 binding confirmed 时应调用 getProviderWorkspacePrefs('x'),且仅接受 provider==='x' 且 bindingId 匹配的推送/响应),避免后续改动把 X 误路由到 Telegram 或 Slack prefs 线。
  x: {
    enabled: false,
    url: '',
    status: 'disabled',
    lastError: null,
    available: false,
    capabilityPending: false,
    binding: null,
  },

Copilot review 建议:X 卡此前只有 fixture 覆盖,无行为用例。补上:
- 端点清单缺 xHookWsUrl 时 X 卡整体不渲染(灰度语义)
- 绑定 pending 时 OAuth 深链动作可见,openApp 调 openProviderAction('x','connect')
- confirmed 动作按 wire actions 数据驱动,X 不渲染 add_to_group
- prefs hook 按 provider='x' 拉取,跨 provider / 跨 bindingId 推送不落进 X 线

Signed-off-by: Dash <dashhuang@gmail.com>
Copilot AI review requested due to automatic review settings July 31, 2026 14:47
@dashhuang

Copy link
Copy Markdown
Member Author

Copilot 复审中两条被抑制的测试覆盖建议已在 04270817 落实:X 设置卡新增 3 条行为用例(端点缺失时卡隐藏 / pending 深链动作走 openProviderAction('x','connect') / confirmed 动作按 wire actions 数据驱动且无 add_to_group),prefs hook 新增 X 镜像用例(按 provider=x 拉取,跨 provider 与跨 bindingId 推送均被围栏丢弃)。另:code-review / review` 此前一次失败为 LLM 代理瞬时故障(1 turn、$0 即 is_error),已重跑。

Copilot AI 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.

Pull request overview

Copilot reviewed 39 out of 40 changed files in this pull request and generated no new comments.

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

Heavy review 通过。navigation-escape 的唯一出口 openXUrl 经过 validateXExternalUrl 严格白名单(HTTPS-only、x.com 精确匹配、参数集固定、S256 PKCE、16 条否决测试);schema 扩枚举无需 migration;preload 只做 type widening 不暴露新 IPC;所有路由 fail-closed。安全软命中(测试里的 user:pw@x.com)确认为否决用例桩。无 P0/P1。

@MagicLizi
MagicLizi merged commit 7e9b93e into main Jul 31, 2026
13 of 14 checks passed
@MagicLizi
MagicLizi deleted the dash/x-provider-client branch July 31, 2026 15:47
@MagicLizi

Copy link
Copy Markdown
Contributor

合了,X hook provider 接线完成。validateXExternalUrl 那套 16 条否决用例很扎实,fail-closed 的路由和 PKCE 强制都在位——以后接 provider 照着这个模子来就对了。

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants