Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ WeChat original voice can be prepared for playback, native quotes and retained l

### Changed

- The External connectors entry no longer offers **Add connector** or **Authorize a conversation** while syncing is redesigned around connecting any app's conversation; it lists existing syncs and keeps **Save a send target (advanced)** for apps that can't post to conversations directly. A conversation row shows where it is synced, and its actions (**Mute**, **Rules**, **Block**) sit on their own row with a tooltip each. The Lark setup guide shrinks to three steps (connect the app, bind it, send a test message), and the Lark, Slack and WeChat guides are rewritten around **Bind app** ([#1113](https://github.com/BotHarness/BotHarness/issues/1113), [Lark guide](docs/lark-connection.md), [External connectors guide](docs/channel-sidebar/external-connectors.md)).

- A Bot's model and wake policy moved from its Profile to two new entries in the DM's Channel sidebar, **Model** and **Wake policy**. Each shows its current value in the collapsed header, lists one row per setting, and opens a dialog to edit; both can be reordered or hidden like other entries. The Model dialog now lists a **Main model** and a **Task model**, each picked from a searchable list with its reasoning effort; models can be set without any preset, a saved preset can still fill the dialog, and **Save as preset** keeps the current settings for reuse. **Attention policy** is now called **Wake policy** ([#1084](https://github.com/BotHarness/BotHarness/issues/1084), [Model guide](docs/channel-sidebar/model.md), [Wake policy guide](docs/channel-sidebar/wake-policy.md)).
- A Bot's IM settings moved from its Profile to two new entries in the DM's Channel sidebar. **External identities** lists each bound identity as a row with its availability and an on/off switch, plus **Bind identity**, the Lark setup guide, IM administrator pairing and Lark approval notifications. **External connectors** lists one row per connector with its state and an on/off switch, plus **Add connector** and conversation authorization. Clicking a row opens a dialog to edit it, with the same options as before. **Channel connectors** are now called **External connectors**. The SOUL.md and MEMORY.md standing limits became one row under **Memory files** that opens a dialog. The moved forms now use the shared dropdowns, inputs and checkboxes ([#1085](https://github.com/BotHarness/BotHarness/issues/1085), [External identities guide](docs/channel-sidebar/external-identities.md), [External connectors guide](docs/channel-sidebar/external-connectors.md)).

Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@

### Changed

- 「外部连接器」不再提供 **添加外部连接器** 和 **授权外部会话**(同步正在围绕“接入任意应用的会话”重新设计),只列出已有的同步,并保留 **保存发送目标(高级)** 给不能直接发往会话的应用。会话行会显示已同步到哪里,操作按钮(**静音**、**规则**、**屏蔽**)单独一行并各带说明提示。Lark 配置引导缩减为三步(连接应用、绑定、发消息验证),Lark、Slack、微信连接教程围绕 **绑定应用** 重写([#1113](https://github.com/BotHarness/BotHarness/issues/1113)、[Lark 教程](docs/lark-connection.md)、[外部连接器说明](docs/channel-sidebar/external-connectors.md))。

- Bot 的模型和唤醒策略从 Profile 移到私聊 Channel sidebar 的两个新分区 **模型** 与 **唤醒策略**:收起时标题右侧显示当前值,每项设置一行,点击打开弹窗修改,并可像其他分区一样排序或隐藏。模型弹窗改为 **主模型** 与 **执行模型** 两项,可输入过滤选择模型并选思考强度;不建预设也能直接保存,已有预设仍可用来填入,**另存为预设** 可把当前设置留作复用。**提醒策略** 改名为 **唤醒策略**([#1084](https://github.com/BotHarness/BotHarness/issues/1084),[模型教程](docs/channel-sidebar/model.md),[唤醒策略教程](docs/channel-sidebar/wake-policy.md))。
- Bot 的 IM 设置从 Profile 移到私聊 Channel sidebar 的两个新分区。**外部身份** 每个已绑定身份一行,显示可用状态和启用开关,下面是 **绑定身份**、Lark 配置引导、IM 管理员配对和 Lark 审批通知。**外部连接器** 每个连接器一行,显示状态和启用开关,下面是 **添加外部连接器** 和外部会话授权。点击一行打开弹窗修改,选项与原来一致。**频道连接器** 改名为 **外部连接器**。SOUL.md 和 MEMORY.md 的常驻记忆上限变成 **记忆文件** 下的一行,点击打开弹窗。迁移后的表单统一使用共享的下拉框、输入框和复选框([#1085](https://github.com/BotHarness/BotHarness/issues/1085),[外部身份教程](docs/channel-sidebar/external-identities.md),[外部连接器教程](docs/channel-sidebar/external-connectors.md))。

Expand Down
18 changes: 17 additions & 1 deletion CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -435,9 +435,25 @@ The membership state of a Channel that belongs to no Channel section. Ungrouped
_Avoid_: default folder, inbox, fixed bottom bucket

**Bridge**:
A configured connection from an external source, such as an IM conversation or later a webhook, to an explicit Channel or PersonaBot Inbox target; it carries inbound delivery and exposes outbound capabilities without becoming the Actor. The UI calls it an External connector (外部连接器); the PersonaBot's own external identity is a separate thing.
A configured connection from an external source, such as an IM conversation or later a webhook, to an explicit Channel or PersonaBot Inbox target; it carries inbound delivery and exposes outbound capabilities without becoming the Actor. For an IM conversation it is listed under External connectors (外部连接器); the PersonaBot's own external identity is a separate thing.
_Avoid_: integration, adapter, connector (bare)

**App**:
The UI name (应用) for one authenticated Provider account, such as a Lark app, a Slack app, a Discord bot or a paired WeChat Bot. An App is bound to at most one PersonaBot; a PersonaBot may bind several Apps, including several of one platform. Settings → IM apps lists every App and the Bot that uses it.
_Avoid_: IM account (in UI copy), connector, integration

**Default traffic**:
The messages an enabled external identity Binding admits without any per-conversation consent: direct messages to the App and group messages the qualified Provider reports as mentioning it. Where the App can be reached is decided on the platform; ordinary group text, followed threads and Channel syncs stay explicit.
_Avoid_: all messages, authorized traffic, open intake

**Conversation entry**:
The per-conversation anchor of one Binding's traffic, stored as a Messaging Grant. An _implicit_ entry is recorded on the first admitted default-traffic message or first proactive post; an _explicit_ entry comes from a saved send target. A _held_ entry waits for the Human (Ask me first, or a bound was reached) and keeps only metadata. A _blocked_ conversation has a durable block keyed by Bot, App fingerprint, kind and ID that refuses it until **Allow again**. Muting an entry keeps admission but never wakes the Bot.
_Avoid_: authorization (for implicit entries), delivery target, subscription

**New-conversation mode**:
A Binding's choice for a conversation that has no entry yet: `auto` (Admit automatically, the default) records an implicit entry and admits the message; `ask` (Ask me first) holds it. Auto-creation is bounded at 20 new entries per hour and 500 active entries per Binding.
_Avoid_: whitelist, approval mode, auto-reply

**Bot Inbox**:
The PersonaBot-level view of Source Events admitted for its attention, whether or not an event belongs to a Channel. It is not a second content store: reading is an explicit act, and ignoring is allowed.
_Avoid_: queue, mailbox, backlog
Expand Down
18 changes: 17 additions & 1 deletion CONTEXT.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -433,9 +433,25 @@ Channel 不属于任何 Channel section 时的 membership state。未分组 Chan
_避免使用_:default folder、inbox、fixed bottom bucket

**Bridge**:
从 external source(如 IM 会话,未来还有 webhook)到某个显式 Channel 或 PersonaBot Inbox target 的已配置连接;它承载 inbound delivery 并暴露 outbound capability,但不会成为 Actor。UI 上称为「外部连接器 / External connector」;PersonaBot 自己的外部身份是另一回事。
从 external source(如 IM 会话,未来还有 webhook)到某个显式 Channel 或 PersonaBot Inbox target 的已配置连接;它承载 inbound delivery 并暴露 outbound capability,但不会成为 Actor。对于 IM 会话,它列在「外部连接器 / External connector」中;PersonaBot 自己的外部身份是另一回事。
_避免使用_:integration、adapter、裸用 connector

**App**:
UI 上叫「应用」:一个已认证 Provider account 的名称,例如 Lark 应用、Slack 应用、Discord bot 或已配对的微信 Bot。一个应用最多绑定到一个 PersonaBot;一个 PersonaBot 可以绑定多个应用,包括同一平台的多个应用。「设置 → IM 应用」列出每个应用及使用它的 Bot。
_避免使用_:UI 文案里的「IM账号」、connector、integration

**Default traffic**:
启用的外部身份 Binding 无需逐会话同意即可接收的消息:发给应用的私聊,以及合格 Provider 报告为 @ 该应用的群消息。谁能触达应用由平台决定;群里的普通文字、跟进的话题和 Channel 同步仍需显式开启。
_避免使用_:全部消息、已授权流量、开放收件

**Conversation entry**:
一个 Binding 的单个会话流量所挂靠的锚点,存为 Messaging Grant。_隐式_ 条目在第一条被接收的默认流量消息或第一次主动发送时记录;_显式_ 条目来自保存的发送目标。_等待处理_ 的条目等 Human 决定(先问我,或达到上限),只保留元数据。_已屏蔽_ 的会话有一个按 Bot、应用指纹、会话类型和 ID 记录的持久屏蔽,直到 **再次允许** 前都会被拒绝。静音的条目照常接收,但不会唤醒 Bot。
_避免使用_:授权(指隐式条目时)、投递目标、订阅

**New-conversation mode**:
Binding 对尚无条目的会话的处理方式:`auto`(自动接收,默认)记录隐式条目并接收消息;`ask`(先问我)把它放到等待处理。自动创建有上限:每个 Binding 每小时 20 个新条目、同时 500 个活跃条目。
_避免使用_:白名单、审批模式、自动回复

**Bot Inbox**:
PersonaBot 层级的 view,包含被 admit 供其 attention 的 Source Event,无论 event 是否属于某个 Channel。它不是第二个 content store:读取是一项显式行为,也允许 ignore。
_避免使用_:queue、mailbox、backlog
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion docs/architecture/botharness-architecture.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,14 @@ sequenceDiagram
M->>DB: append attempt and outcome facts
```

A Source Event is the sole authority for content; Channels and Inboxes hold relationships only. A Reply follows the trusted Reply Route so the Host selects the source provider. A proactive post is a Service Action and requires both Provider Capability and a Human Service Grant. A SQLite transaction covers local facts only. External effects use an Outbox Intent, a stable idempotency identity, and bounded reconciliation without claiming exactly-once delivery. An outcome that cannot be proven becomes `unknown-outcome` for Human resolution.
A Source Event is the sole authority for content; Channels and Inboxes hold relationships only. A Reply follows the trusted Reply Route so the Host selects the source provider. A proactive post is a Service Action and requires Provider Capability plus either the Bot's conversation entry for a conversation the App can reach or, as a fallback, a Human saved-target Service Grant. A SQLite transaction covers local facts only. External effects use an Outbox Intent, a stable idempotency identity, and bounded reconciliation without claiming exactly-once delivery. An outcome that cannot be proven becomes `unknown-outcome` for Human resolution.

Wake Policy decides when an Orchestrator observes new attention: at the safe boundary after the current step, after the current turn, or by starting a new turn while idle. Ordinary external messages do not interrupt a running model/tool step. Only a DSH-supported and policy-authorized control path may steer execution. Ready attention is consumed by turn, not by event: while a turn runs, arrivals mark a ready set, and one harvest turn consumes it when the turn ends or the Bot is idle; only direct mentions and DMs steer into the running turn (ADR-0077). Wake handling follows the Source class rather than the platform: external providers normalize into Source Events at the Bridge, and the runtime branches only on Source class and admission reason (ADR-0075).

### Bound apps admit default traffic (ADR-0142)

Reception is keyed by the external identity Binding, not by a saved target. An enabled Binding admits its App's default traffic, direct messages and qualified group mentions, into the bound Bot's Inbox. The first admitted message from a conversation commits an implicit conversation entry (a `messaging_grants` row with `origin: 'implicit'`) in the same transaction as its Source Event and Inbox Admission, so Outbox fences, group policies, Channel Bridge routes and revocation keep one anchor. The Binding's new-conversation mode (`auto` or `ask`) and its bounds (20 new entries per hour, 500 active, 200 held) decide whether a new conversation is admitted or held. A block is durable per Bot, App fingerprint, conversation kind and ID; mute moves only `preferenceRevision`, leaving the entry's Outbox revision untouched. A Bot may bind several Apps of one platform; each App still belongs to one Bot. In the Client the App's conversation list manages entries and shows their existing Channel Bridge routes (creating a sync is being redesigned around External connectors), and the External connectors entry lists those routes and keeps saved-target Service Grants as the advanced fallback for Providers that can't list or address conversations.

### Local Human names — target design (ADR-0103)

The local Human has one optional default display name within the DSH Profile, edited in BotHarness plugin settings and falling back to `Human`. Every Human-participating DM or Group Channel may override it with **Human Channel nickname**, edited through “My nickname” in the Channel header menu. Clearing an override restores inheritance; changing the default affects only Channels without an override. These names support roleplay with different partners without adding saved roleplay backgrounds, another Human account, or another Human Inbox.
Expand Down
6 changes: 5 additions & 1 deletion docs/architecture/botharness-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,14 @@ sequenceDiagram
M->>DB: append attempt and outcome facts
```

Source Event 是内容唯一权威;Channel 和 Inbox 都只保存关系。Reply 使用可信 Reply Route 自动选择来源 provider;主动发布属于 Service Action,必须同时满足 Provider Capability 与 Human Service Grant。SQLite 事务只覆盖本地事实;外部副作用使用 Outbox Intent、幂等标识和有界 reconciliation,不宣称 exactly-once。不可证明的结果进入 `unknown-outcome`,由 Human 处理。
Source Event 是内容唯一权威;Channel 和 Inbox 都只保存关系。Reply 使用可信 Reply Route 自动选择来源 provider;主动发布属于 Service Action,需要 Provider Capability,以及该 Bot 对应用可触达会话的会话条目,或作为后备的 Human 保存目标 Service Grant。SQLite 事务只覆盖本地事实;外部副作用使用 Outbox Intent、幂等标识和有界 reconciliation,不宣称 exactly-once。不可证明的结果进入 `unknown-outcome`,由 Human 处理。

Wake Policy 决定何时让 Orchestrator 看见新 attention:当前 step 完成后的安全边界、当前 turn 结束后,或 idle 时启动新 turn。普通外部消息不打断正在执行的 model/tool step;只有 DSH 明确支持且策略授权的控制路径才能 steer。就绪的 attention 按回合收割:忙碌期间新到的事件只把就绪集合置脏,当前回合结束(即空闲)时由一次 harvest turn 消费全部就绪项;主动 steer 只用于直接 @ 与 DM(ADR-0077)。

### 绑定的应用接收默认流量(ADR-0142)

接收以外部身份 Binding 为键,而不是保存的目标。启用的 Binding 把应用的默认流量(私聊和合格的群 @)接收进绑定 Bot 的 Inbox。会话的第一条被接收的消息,会与其 Source Event、Inbox Admission 在同一事务中提交一个隐式会话条目(`messaging_grants` 中 `origin: 'implicit'` 的行),使 Outbox fence、群策略、Channel Bridge 路由和撤销仍挂在同一个锚点上。Binding 的新会话模式(`auto` 或 `ask`)及其上限(每小时 20 个新条目、500 个活跃、200 个等待)决定新会话被接收还是等待处理。屏蔽按 Bot、应用指纹、会话类型和 ID 持久保存;静音只推进 `preferenceRevision`,不改动条目的 Outbox revision。一个 Bot 可以绑定同一平台的多个应用,每个应用仍只属于一个 Bot。Client 中,应用的会话列表管理这些条目并显示已有的 Channel Bridge 路由(新建同步正在围绕外部连接器重新设计),「外部连接器」列出这些路由并保留保存目标的 Service Grant,作为 Provider 无法列出或直接发往会话时的高级后备。

[#824](https://github.com/BotHarness/BotHarness/issues/824) 在 PersonaBot Profile 增加可恢复的配置引导,本地打包的 Driver.js 定位既有原生 IM 设置、身份与群授权控件。进度只投影当前兼容 Provider、账号、Binding/Grant、已收测试 Source Event 和沿原来源回复的 Outbox 回执;可选的认证自身回传仍单独呈现。平台接受、外部可见投递和已读回执明确区分。不建立新手引导数据库、额外凭据存储或消息权威;打开和关闭引导不产生授权或发送。

### 首条外部出站路径(ADR-0101)
Expand Down
24 changes: 24 additions & 0 deletions docs/assets/pr/1113-connectors-relabel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# #1113 External connectors relabel

Captured from a real DSH 0.2.0-rc.1 instance with the QA fake IM provider and the real OpenCode Go model.

## Conversation rows: actions on their own row, a tooltip on each

| | Light | Dark |
| --- | -------------------------- | ------------------------- |
| zh | ![](rows-v4-zh-light.webp) | ![](rows-v4-zh-dark.webp) |
| en | ![](rows-v4-en-light.webp) | ![](rows-v4-en-dark.webp) |

## External connectors: syncs plus the advanced send target

| | Light | Dark |
| --- | ------------------------ | ----------------------- |
| zh | ![](conns-zh-light.webp) | ![](conns-zh-dark.webp) |
| en | ![](conns-en-light.webp) | ![](conns-en-dark.webp) |

## Lark setup guide: three steps

| | Light | Dark |
| --- | --------------------------- | -------------------------- |
| zh | ![](guide-v2-zh-light.webp) | ![](guide-v2-zh-dark.webp) |
| en | ![](guide-v2-en-light.webp) | ![](guide-v2-en-dark.webp) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading