diff --git a/.gitattributes b/.gitattributes index cb7d7f2c2e..e4dc913758 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,3 +4,5 @@ apps/docs/public/guides/vps-source/terminal/*.typescript -text -diff apps/docs/public/guides/vps-source/terminal/*.timing -text -diff # Preserve the pinned upstream WebRTC notice material verbatim. apps/mobile/modules/local-computer-video/android/src/main/assets/local-computer-video/THIRD-PARTY-NOTICES.md -whitespace +# pnpm parses patches byte for byte; keep them LF on Windows checkouts. +patches/*.patch text eol=lf diff --git a/changes/2918-im-provider-qq-lark.md b/changes/2918-im-provider-qq-lark.md new file mode 100644 index 0000000000..1376fa01a1 --- /dev/null +++ b/changes/2918-im-provider-qq-lark.md @@ -0,0 +1,13 @@ +--- +section: Fixed +--- + +## en + +- The bundled IM Provider moves to `4.32.0-botharness.23` and ships the QQ fixes. Bots on DSH 0.2.1 can create sessions again instead of failing with `INTERNAL_UNKNOWN` ([#2896](https://github.com/BotHarness/DeepSeekBot/issues/2896)). Quoted, image and mixed QQ messages are no longer dropped ([#2895](https://github.com/BotHarness/DeepSeekBot/issues/2895)). Concurrent QQ group replies retry on 429 ([#2897](https://github.com/BotHarness/DeepSeekBot/issues/2897)). Late QQ results are delivered as passive replies ([#2868](https://github.com/BotHarness/DeepSeekBot/issues/2868)). QQ private messages arrive in Bot mode ([#2918](https://github.com/BotHarness/DeepSeekBot/issues/2918)). +- Lark Bot mode replies that use Markdown are sent as a native Markdown card, so bold text, headings, lists and tables no longer show raw symbols. Plain replies and replies that @ someone stay text ([#2792](https://github.com/BotHarness/DeepSeekBot/issues/2792)). + +## zh + +- 内置 IM Provider 升级到 `4.32.0-botharness.23`,包含 QQ 修复。DSH 0.2.1 上的 Bot 可以重新创建会话,不再报 `INTERNAL_UNKNOWN`([#2896](https://github.com/BotHarness/DeepSeekBot/issues/2896))。QQ 的引用、图片和图文混合消息不再丢失([#2895](https://github.com/BotHarness/DeepSeekBot/issues/2895))。QQ 群内并发回复遇到 429 会重试([#2897](https://github.com/BotHarness/DeepSeekBot/issues/2897))。迟到的 QQ 结果会以被动回复送达([#2868](https://github.com/BotHarness/DeepSeekBot/issues/2868))。Bot 模式可以收到 QQ 私聊([#2918](https://github.com/BotHarness/DeepSeekBot/issues/2918))。 +- 飞书 Bot 模式中使用 Markdown 的回复改为原生 Markdown 卡片发送,加粗、标题、列表和表格不再显示原始符号。纯文本回复和 @ 他人的回复仍按文本发送([#2792](https://github.com/BotHarness/DeepSeekBot/issues/2792))。 diff --git a/docs/client-bridge.md b/docs/client-bridge.md index 380081b390..ad10477d5b 100644 --- a/docs/client-bridge.md +++ b/docs/client-bridge.md @@ -144,7 +144,7 @@ resolver cannot substitute workspace-linked Core/Client for the tarballs. node scripts/dev-instance.mjs --home /tmp/bh-im-qa --port 31968 --im-provider --json ``` -仅对已停止的隔离 Profile 执行;重启同一 Profile 时仍传入 `--im-provider`,以重复校验。当前 Provider 来源记录为 Git 完整提交 `beaed4a6dabb583654d28fb09298716267039b4a`,开发资格记录为 DSH `0.2.1-rc.2`,这些来源记录不限制实际启动的 DSH 版本;校验 Bundle、入口及运行时代码 digest 后才启动 Host;不依赖另一份 provider 本地源码。安装摘要明确标注 `upstreamReleased: false`。此完整 fork 保留附件、回显与独立回复身份契约;群/话题上下文读取绑定当前独占 Consumer 生命周期,释放或替换后拒绝返回正在读取的结果;上游 PR 是否合并不阻挡此固定提交使用([#789](https://github.com/BotHarness/BotHarness/issues/789))。默认启动不安装它,原 npm `4.32.0` 仍不满足账号校验和条件发送契约。此入口不会发布包,也不是生产启用许可([ADR-0104](adr/0104-isolated-im-profiles-pin-a-qualified-temporary-provider-fork.md))。 +仅对已停止的隔离 Profile 执行;重启同一 Profile 时仍传入 `--im-provider`,以重复校验。当前 Provider 来源记录为 Git 完整提交 `7505ce6fcda26c02810781fde9d4da81dab28a68`,开发资格记录为 DSH `0.2.1-rc.2`,这些来源记录不限制实际启动的 DSH 版本;校验 Bundle、入口及运行时代码 digest 后才启动 Host;不依赖另一份 provider 本地源码。安装摘要明确标注 `upstreamReleased: false`。此完整 fork 保留附件、回显与独立回复身份契约;群/话题上下文读取绑定当前独占 Consumer 生命周期,释放或替换后拒绝返回正在读取的结果;上游 PR 是否合并不阻挡此固定提交使用([#789](https://github.com/BotHarness/BotHarness/issues/789))。默认启动不安装它,原 npm `4.32.0` 仍不满足账号校验和条件发送契约。此入口不会发布包,也不是生产启用许可([ADR-0104](adr/0104-isolated-im-profiles-pin-a-qualified-temporary-provider-fork.md))。 在 dsh-im 原设置中配置测试应用,并保存、测试仅含测试者与 Bot 的目标群;凭据交由 DSH credentials service,不复制到 BotHarness。打开 PersonaBot Profile → IM connection,选择已认证账号与已测试目标,显式授权后发送一条唯一测试文本。预期 Recent sends 显示 Platform accepted,并在目标群核对同一文本;这不代表送达或已读。停止本次启动摘要中的确切 PID,再以相同参数启动:绑定与发送历史应保留,不自动重发。 diff --git a/docs/product-im-installation.md b/docs/product-im-installation.md index 40670488ac..7dd22d7a75 100644 --- a/docs/product-im-installation.md +++ b/docs/product-im-installation.md @@ -35,7 +35,7 @@ fails before packing. ```bash git clone https://github.com/DoodleBears/dsh-im.git /tmp/bh-im-source -git -C /tmp/bh-im-source checkout beaed4a6dabb583654d28fb09298716267039b4a +git -C /tmp/bh-im-source checkout 7505ce6fcda26c02810781fde9d4da81dab28a68 npm ci --prefix /tmp/bh-im-source --ignore-scripts --no-audit --no-fund pnpm install --frozen-lockfile pnpm build diff --git a/patches/react-native-view-shot@6.1.1.patch b/patches/react-native-view-shot@6.1.1.patch index 1647d14586..3e3202fb0a 100644 --- a/patches/react-native-view-shot@6.1.1.patch +++ b/patches/react-native-view-shot@6.1.1.patch @@ -1,6 +1,3 @@ -diff --git a/example-expo/package-lock.json b/example-expo/package-lock.json -deleted file mode 100644 -index bd111b097ef17c42d7651e3dff1bda899e6cbeac..0000000000000000000000000000000000000000 diff --git a/package.json b/package.json index e42f799471b5a811919f936a5d4fda7b5df5cc9b..4d7a7bc5ae90d2745bbfe4bb94795dc2e5e1a6b3 100644 --- a/package.json diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e7c46f39c2..8e323beb2a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -173,7 +173,7 @@ patchedDependencies: '@deepseek-ai/dsh-tool-fs@0.2.1-rc.3': 4b2e510cb0df4904b95b99936edd4cdaec5b19438561254906b3abf0d2c3b204 dockview-core@8.4.1: 6d5f9165424be95472edbb4e667b16cf9abd150f139d3524cc1ca9a6b7863b86 expo-quick-actions@6.0.2: 2d9cefa269045271145e1989e004232aac3c206249494311d39f49c13293dddb - react-native-view-shot@6.1.1: 1a309afc15955797ee9174234ae2514e981ea99e97527650b1d0ed0ebe6ee9ca + react-native-view-shot@6.1.1: a288c04a105e6e1b53da39a97f1b500ae8375b9967c3fc6cbac861efc0b9a5b2 importers: @@ -482,7 +482,7 @@ importers: version: 4.3.4(react-native-pager-view@9.0.7(react-native@0.88.0(@babel/core@7.29.7(supports-color@10.2.2))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2))(@types/react@19.3.0)(react@19.3.0)(supports-color@10.2.2))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7(supports-color@10.2.2))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2))(@types/react@19.3.0)(react@19.3.0)(supports-color@10.2.2))(react@19.3.0) react-native-view-shot: specifier: 6.1.1 - version: 6.1.1(patch_hash=1a309afc15955797ee9174234ae2514e981ea99e97527650b1d0ed0ebe6ee9ca)(react-native@0.88.0(@babel/core@7.29.7(supports-color@10.2.2))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2))(@types/react@19.3.0)(react@19.3.0)(supports-color@10.2.2))(react@19.3.0) + version: 6.1.1(patch_hash=a288c04a105e6e1b53da39a97f1b500ae8375b9967c3fc6cbac861efc0b9a5b2)(react-native@0.88.0(@babel/core@7.29.7(supports-color@10.2.2))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2))(@types/react@19.3.0)(react@19.3.0)(supports-color@10.2.2))(react@19.3.0) react-native-web: specifier: ~0.21.4 version: 0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0) @@ -25706,7 +25706,7 @@ snapshots: react-native-pager-view: 9.0.7(react-native@0.88.0(@babel/core@7.29.7(supports-color@10.2.2))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2))(@types/react@19.3.0)(react@19.3.0)(supports-color@10.2.2))(react@19.3.0) use-latest-callback: 0.2.6(react@19.3.0) - react-native-view-shot@6.1.1(patch_hash=1a309afc15955797ee9174234ae2514e981ea99e97527650b1d0ed0ebe6ee9ca)(react-native@0.88.0(@babel/core@7.29.7(supports-color@10.2.2))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2))(@types/react@19.3.0)(react@19.3.0)(supports-color@10.2.2))(react@19.3.0): + react-native-view-shot@6.1.1(patch_hash=a288c04a105e6e1b53da39a97f1b500ae8375b9967c3fc6cbac861efc0b9a5b2)(react-native@0.88.0(@babel/core@7.29.7(supports-color@10.2.2))(@react-native/metro-config@0.87.1(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2))(@types/react@19.3.0)(react@19.3.0)(supports-color@10.2.2))(react@19.3.0): dependencies: react: 19.3.0 optionalDependencies: diff --git a/scripts/dev-im-provider.mjs b/scripts/dev-im-provider.mjs index ae99f30a47..ee3fa2b6f4 100644 --- a/scripts/dev-im-provider.mjs +++ b/scripts/dev-im-provider.mjs @@ -5,11 +5,11 @@ import { join } from 'node:path'; export const qualifiedImProvider = Object.freeze({ package: '@xmanrui/dsh-im', packageVersion: '4.32.0', - source: 'beaed4a6dabb583654d28fb09298716267039b4a', - spec: 'github:DoodleBears/dsh-im#beaed4a6dabb583654d28fb09298716267039b4a', + source: '7505ce6fcda26c02810781fde9d4da81dab28a68', + spec: 'github:DoodleBears/dsh-im#7505ce6fcda26c02810781fde9d4da81dab28a68', dsh: '0.2.1-rc.2', - runtimeFiles: 421, - runtimeSha256: '42e1140e67ba2f74122db3d49bb2c8aece239b7d75f9564ce713a8a491902706', + runtimeFiles: 424, + runtimeSha256: 'a4429580ebf70b08e19394cea97d7d0db9b86b06e1c92f294a28144378537d46', }); export function withQualifiedImProvider(manifest) { diff --git a/scripts/product-artifacts.mjs b/scripts/product-artifacts.mjs index 45e4ab930e..33683ac7d3 100644 --- a/scripts/product-artifacts.mjs +++ b/scripts/product-artifacts.mjs @@ -20,16 +20,16 @@ export const productDshVersions = Object.freeze(['0.2.0-rc.2', '0.2.1-rc.2', pro export const productImProvider = Object.freeze({ name: '@botharness/im-provider', - version: '4.32.0-botharness.22', + version: '4.32.0-botharness.23', sourceManifestSha256: '3331e8f771a91abf396eb4e7ed5c0acc4c3b504cdccc7d715e37062708384cc2', sourceLockSha256: '3476c34c7d4515000d2617beaf2568b2a794b60de9b350cd8eafb7a2bf21adef', upstream: Object.freeze({ package: '@xmanrui/dsh-im', packageVersion: '4.32.0', - source: 'beaed4a6dabb583654d28fb09298716267039b4a', + source: '7505ce6fcda26c02810781fde9d4da81dab28a68', dsh: '0.2.0-rc.2', - runtimeFiles: 421, - runtimeSha256: '42e1140e67ba2f74122db3d49bb2c8aece239b7d75f9564ce713a8a491902706', + runtimeFiles: 424, + runtimeSha256: 'a4429580ebf70b08e19394cea97d7d0db9b86b06e1c92f294a28144378537d46', }), }); diff --git a/scripts/test/npm-prerelease.test.mjs b/scripts/test/npm-prerelease.test.mjs index 14d8f8f7f8..59e63b5922 100644 --- a/scripts/test/npm-prerelease.test.mjs +++ b/scripts/test/npm-prerelease.test.mjs @@ -4,6 +4,7 @@ import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'nod import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { afterEach, describe, expect, it, vi } from 'vitest'; +import semver from 'semver'; import { awaitPublished, assertCleanReleaseSource, @@ -144,10 +145,11 @@ describe('reviewed npm prerelease', () => { it('pins the published product Provider separately from historical standalone publication', () => { expect(publishedProductProvider).toMatchObject({ name: productImProvider.name, - version: productImProvider.version, - providerSource: productImProvider.upstream.source, distTag: 'latest', }); + if (publishedProductProvider.version === productImProvider.version) + expect(publishedProductProvider.providerSource).toBe(productImProvider.upstream.source); + else expect(semver.gt(productImProvider.version, publishedProductProvider.version)).toBe(true); expect(publishedProductProvider.version).toMatch(/^\d+\.\d+\.\d+-botharness\.\d+$/); expect(publishedProductProvider.providerSource).toMatch(/^[a-f0-9]{40}$/); expect(publishedProductProvider.productSource).toMatch(/^[a-f0-9]{40}$/); diff --git a/scripts/test/product-artifacts.test.mjs b/scripts/test/product-artifacts.test.mjs index 24b1306787..83c5906d11 100644 --- a/scripts/test/product-artifacts.test.mjs +++ b/scripts/test/product-artifacts.test.mjs @@ -324,7 +324,7 @@ describe('release composition', () => { expect(() => verifyProductComposition(entries)).toThrow('conflicts'); }); it('keeps product provenance independent when the development Provider selection changes', () => { - expect(productImProvider.upstream.source).toBe('beaed4a6dabb583654d28fb09298716267039b4a'); + expect(productImProvider.upstream.source).toBe('7505ce6fcda26c02810781fde9d4da81dab28a68'); expect(productImProvider.upstream.dsh).toBe('0.2.0-rc.2'); }); @@ -339,7 +339,7 @@ describe('release composition', () => { '@botharness/computer': '0.0.0-test.823', '@botharness/core': '0.0.0-test.823', '@botharness/ui': '0.0.0-test.823', - '@botharness/im-provider': '4.32.0-botharness.22', + '@botharness/im-provider': '4.32.0-botharness.23', }); expect(release.optionalDependencies).toEqual( Object.fromEntries(cloudflaredPackageNames.map((name) => [name, '0.0.0-test.823'])),