Document bridge-only provider architecture

This commit is contained in:
Haitao Pan 2026-04-10 15:00:58 +08:00
parent 64e46725d7
commit a8a1a25fc9
2 changed files with 134 additions and 34 deletions

View File

@ -1,50 +1,84 @@
# Settings Integration Configuration Model
This document records the logical model behind the Settings -> Integrations page.
This document records the current logical model behind Settings -> Integrations,
with the provider catalog aligned to the bridge-only design.
The page is organized into three layers:
## Current Rule
- User login state
- Base connection configuration
- Advanced custom mode
- Settings only manages bridge connection parameters and upstream sync
definitions.
- The provider picker is not derived from local endpoint presets.
- `xworkmate-bridge` is the only source of truth for the provider catalog.
The base connection layer is the default configuration surface. It represents the connection identity that can come from either `svc.plus` or a self-hosted service. Advanced custom mode does not replace the base layer; it overrides selected defaults on top of it.
## Bridge-Only Provider Source Of Truth
```mermaid
flowchart TD
A[Settings Integrations Page] --> B[User Login State]
A --> C[Base Connection Configuration]
A --> D[Advanced Custom Mode]
A["Settings UI
仅管理 Bridge 连接参数
与自定义 upstream sync 定义"] --> B["SettingsSnapshot.externalAcpEndpoints
仅作为 sync 输入"]
B --> B1[Signed out]
B --> B2[Signed in]
B --> B3[MFA pending]
B --> B4[Signing in]
B --> C["buildExternalAcpSyncedProvidersInternal()"]
C --> D["syncExternalAcpProvidersInternal()"]
D --> E["xworkmate.providers.sync"]
E --> F["xworkmate-bridge providerCatalog"]
C --> C1[Account / Email]
C --> C2[Password]
C --> C3[Service URL]
C --> C4[User]
C --> C5[Sync]
C --> C6[Default connection source]
C6 --> C7[svc.plus provided]
C6 --> C8[Self-hosted]
F --> G["acp.capabilities"]
G --> H["providers[]
singleAgent / multiAgent"]
D --> D1[Override OpenClaw Gateway]
D --> D2[Override Vault Server]
D --> D3[Override LLM Endpoint]
D --> D4[Override External ACP Server endpoint]
D --> D5[Override SKILLS directories]
H --> I["refreshSingleAgentCapabilitiesRuntimeInternal()"]
I --> J["bridgeAdvertisedProvidersInternal
App 内唯一 provider 名单源"]
I --> K["singleAgentCapabilitiesByProviderInternal
App 内唯一 provider 可用性源"]
B2 --> C
C --> D
D --> E[Final effective configuration]
G --> L["refreshAcpCapabilitiesRuntimeInternal()"]
L --> M["GatewayAcpCapabilities
providers / singleAgent / multiAgent"]
M --> N["mergeAcpCapabilitiesIntoMountTargetsRuntimeInternal()"]
N --> O["ManagedMountTargetState
codex / opencode / claude / gemini / aris / openclaw
available / discoveryState"]
J --> P["configuredSingleAgentProviders
= bridgeAdvertisedProvidersInternal"]
P --> Q["singleAgentProviderOptions
Composer / Thread Picker 唯一数据源"]
K --> R["availableSingleAgentProviders
= bridge 当前可用 provider"]
R --> S["visibleAssistantExecutionTargets(...)
single-agent 是否显示
只看 runtime available providers"]
O --> T["visible gateway / multi-agent execution affordances
openclaw / aris discovery 只看 bridge capabilities"]
Q --> U["setSingleAgentProvider(providerId)
仅写入 thread executionBinding.providerId"]
U --> V["singleAgentProviderForSession()
恢复线程已选 providerId"]
V --> W["sendSingleAgentMessageDesktopGoTaskFlowInternal()"]
W --> X["再次拉取 acp.capabilities"]
X --> Y["按本次 bridge providers 解析
auto -> 当前 bridge 顺序第一个可用 provider
explicit -> 当前 bridge 已广告的 provider"]
Y --> Z{"provider resolved?"}
Z -->|"yes"| AA["executeTask(... provider ...)"]
Z -->|"no"| AB["provider unavailable UX"]
```
## Notes
- User login state describes authentication only.
- Base connection configuration describes the default connection path and identity.
- Advanced custom mode is a layered override mechanism.
- The effective runtime configuration is computed from the base layer plus any advanced overrides.
- `externalAcpEndpoints` still matters, but only as bridge sync input.
- Provider visibility, picker contents, and auto-provider resolution all come
from `acp.capabilities.providers`.
- `openclaw` and other mount-target discovery states are also bridge-owned and
come from ACP capabilities merged into `ManagedMountTargetState`.
- Persisted thread `providerId` restores the user's previous selection, but it
does not repopulate the provider catalog.

View File

@ -44,6 +44,72 @@ flowchart TD
Q --> R["UI stream render"]
```
## Provider 真源
Single-agent provider catalog and availability are owned by
`xworkmate-bridge`, not by local endpoint presets inside the app.
```mermaid
flowchart TD
A["Settings UI
仅管理 Bridge 连接参数
与自定义 upstream sync 定义"] --> B["SettingsSnapshot.externalAcpEndpoints
仅作为 sync 输入"]
B --> C["buildExternalAcpSyncedProvidersInternal()"]
C --> D["syncExternalAcpProvidersInternal()"]
D --> E["xworkmate.providers.sync"]
E --> F["xworkmate-bridge providerCatalog"]
F --> G["acp.capabilities"]
G --> H["providers[]
singleAgent / multiAgent"]
H --> I["refreshSingleAgentCapabilitiesRuntimeInternal()"]
I --> J["bridgeAdvertisedProvidersInternal
App 内唯一 provider 名单源"]
I --> K["singleAgentCapabilitiesByProviderInternal
App 内唯一 provider 可用性源"]
G --> L["refreshAcpCapabilitiesRuntimeInternal()"]
L --> M["GatewayAcpCapabilities
providers / singleAgent / multiAgent"]
M --> N["mergeAcpCapabilitiesIntoMountTargetsRuntimeInternal()"]
N --> O["ManagedMountTargetState
codex / opencode / claude / gemini / aris / openclaw
available / discoveryState"]
J --> P["configuredSingleAgentProviders
= bridgeAdvertisedProvidersInternal"]
P --> Q["singleAgentProviderOptions
Composer / Thread Picker 唯一数据源"]
K --> R["availableSingleAgentProviders
= bridge 当前可用 provider"]
R --> S["visibleAssistantExecutionTargets(...)
single-agent 是否显示
只看 runtime available providers"]
O --> T["visible gateway / multi-agent execution affordances
openclaw / aris discovery 只看 bridge capabilities"]
Q --> U["setSingleAgentProvider(providerId)
仅写入 thread executionBinding.providerId"]
U --> V["singleAgentProviderForSession()
恢复线程已选 providerId"]
V --> W["sendSingleAgentMessageDesktopGoTaskFlowInternal()"]
W --> X["再次拉取 acp.capabilities"]
X --> Y["按本次 bridge providers 解析
auto -> 当前 bridge 顺序第一个可用 provider
explicit -> 当前 bridge 已广告的 provider"]
Y --> Z{"provider resolved?"}
Z -->|"yes"| AA["executeTask(... provider ...)"]
Z -->|"no"| AB["provider unavailable UX"]
```
## 端侧桥接规则
### Desktop App