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: 1 addition & 1 deletion docs/architecture/cli-product-line-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ CLI 通过 `DeliveryProfile::Cli` 消费经过校验的产品 Runtime parts。

CLI 只消费 typed summary 与 typed action:

> **目标状态,尚未交付:** 当前 `/extensions` 只支持来源状态、刷新、Safe Mode 和来源开关;没有应用级连接动作、`/extensions review` 或任务相关 `action-required`。以下入口必须完成执行计划 P1-P6 及端到端验证后,才能更新为当前能力
> **实现状态:部分交付。** 交互式 TUI 已通过 Host 返回的 V2 快照提供应用级状态、连接、断开、暂不使用和分页批量确认;Embedded 连接旧 Host 时回退既有 V1 只读状态,未接线的 Shared Runtime 明确不支持且绝不回退到控制进程本地执行。任务相关 `action-required` 与非交互 CLI 结果仍未交付

- `/extensions` 是应用级摘要、首次连接和状态恢复入口;`/extensions review` 提供与 GUI 等价的单页批量确认。
- `/tools`、`/agent`、`/mcp` 和 `/hooks` 保留能力专项或高级管理职责,不复制应用级连接流程。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

本文只描述交互、应用级读模型、动作语义和宿主投影,不重定义生态解析、能力归属、执行权限或插件运行时。

> **实现状态:部分交付。** 当前生产协议仍以严格校验的 `ExternalSourceControlSnapshotV1` 为主,Desktop 已交付应用级首页和详情投影;共享应用连接、批量确认和任务相关 `action-required` 仍须完成对应执行计划并取得端到端证据。Hook 管理沿用独立 owner 和现有安全审核契约,其产品入口与展示规则见第 5.5、7.1 和 8.3 节。
> **实现状态:部分交付。** 当前分支保留严格 V1 兼容路径,并已交付独立 V2 应用快照、作用域化连接偏好与迁移、分页批量确认、Desktop/Peer 投影,以及 Desktop Settings 和交互式 TUI 消费。App Server 只在真实注入 management owner 的宿主中暴露这些方法;Shared Runtime 与通用 Server 不伪装支持。任务相关 `action-required`、非交互 CLI 结果和 `HookManagementSnapshot` 仍是后续工作。Hook 管理继续沿用独立 owner 和现有安全审核契约,其产品入口与展示规则见第 5.5、7.1 和 8.3 节。

## 1. 问题与设计目标

Expand Down Expand Up @@ -209,6 +209,7 @@ Tool、Subagent、MCP、Hook 和无法自动决定的真实冲突进入同一个

- stale revision、无效 generation 或宿主能力整体不兼容时,整个请求不应用;
- owner 允许逐项业务拒绝时,响应返回逐项结果;宿主只把成功项标为已启用;
- “整个请求不应用”只保证分派前的 identity、revision 和 generation 预检;开始分派后若 owner 状态并发变化,可以同时返回已应用项和类型化 stale/failed 项,不承诺跨 owner 回滚;
- 未知结果不能假定成功;
- 失败项保留可行动原因与恢复动作。

Expand Down Expand Up @@ -356,7 +357,7 @@ ExternalApplicationReviewPageV2
items[] # 每页最多 128,只含 item reference、显示摘要、推荐与安全上限
```

分页游标必须绑定作用域、`review_id`、偏好版本和发现代次;任一事实变化都返回过期并重新读取,不能把旧页与新页拼接。详细页通过稳定项目引用关联现有 Tool、Subagent、MCP 和冲突投影;总量继续服从现有归属模块上限,完整提示词、命令正文、凭据和可执行载荷不进入分页响应。
首次打开确认页时,请求不带 cursor 和 expected generations;若后台发现已在首页快照后完成,Host 可以返回当前只读确认计划,并以响应中的 `review_id` 和 generations 作为后续翻页与提交的唯一基准。偏好版本、执行域、工作区和目标作用域仍必须完全匹配。首次响应之后,分页游标严格绑定作用域、`review_id`、偏好版本和发现代次;任一事实变化都返回过期并重新读取,不能把旧页与新页拼接。详细页通过稳定项目引用关联现有 Tool、Subagent、MCP 和冲突投影;总量继续服从现有归属模块上限,完整提示词、命令正文、凭据和可执行载荷不进入分页响应。

状态和主操作由共享归属模块派生;React、TUI、Peer 和 Server 不重复实现优先级规则。

Expand Down Expand Up @@ -408,7 +409,7 @@ AgenticEvent::ExternalDependencyActionRequired

现有 `ExternalSourceControlSnapshotV1`、`ExternalSourceControlActionV1`、`ExternalSourceRecoveryActionV1` 和 V1 `hostCapabilities` 保持字段与闭合枚举不变。应用级快照、连接动作、批量确认、`upgrade-host` 语义以及新增能力位不得追加到 V1 对象。

`get_external_application_snapshot_v2` 本身无副作用,直接承担版本探测,不再增加单独的版本信息接口:
`get_external_application_snapshot_v2` 不提交用户决定或运行能力写动作,直接承担版本探测,不再增加单独的版本信息接口。首次激活对应 owner 时允许执行可重入偏好迁移并启动既有后台发现;当前 V2 偏好读取不得重复写回。确认分页只读取已激活 owner 的不可变结果,不能冷启动服务或发现

- 新宿主返回严格的 V2 快照和 `host_capabilities`;客户端校验成功后,才可读取分页确认项或发送 V2 写操作;
- 旧宿主对 V2 快照返回传输层 method-not-found 时,客户端回退显示 V1 来源/能力管理并禁用 V2 写操作;
Expand All @@ -420,7 +421,7 @@ AgenticEvent::ExternalDependencyActionRequired

### 8.2 性能与演进约束

- 应用快照和确认分页必须从当前不可变发现结果派生;读取不能重新扫描文件、启动外部进程或持有偏好写锁。
- 应用快照和确认分页必须从当前不可变发现结果派生;首次快照可触发既有 owner 的迁移和后台发现,确认分页不得重新扫描文件、冷启动 owner、启动外部进程或持有偏好写锁。
- 首页只返回摘要,确认页每页最多 128 项。完整候选总量继续服从各归属模块已有上限,不建立第二套无界缓存。
- 共享缓存只允许按执行域、工作区作用域、发现代次和偏好版本精确失效;React、TUI、Peer 与 Server 不得各自维护产品状态机。
- 归属模块的加载与卸载在锁外执行;迁移关口只阻塞外部来源读写,不阻塞项目打开或无关 Agent 任务。
Expand Down
12 changes: 7 additions & 5 deletions docs/plans/external-ai-app-connection-experience-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

> 本计划把[外部 AI 工作内容总体架构](../architecture/extensions/external-ai-work-sources-design.md)和[外部 AI 应用连接与管理详细设计](../architecture/extensions/external-ai-app-connection-experience-design.md)拆成可独立评审、验证和回退的实施阶段。本文不扩大任何生态的能力兼容范围;OpenCode 具体能力路线仍以[OpenCode 扩展兼容计划](opencode-extension-compatibility-plan.md)为准。

> **实现状态:全部为目标工作。** 当前生产只提供严格 V1 来源/能力控制协议;应用级连接、V2 协议、批量确认、跨宿主应用快照和任务相关 `action-required` 尚未交付。只有完成对应阶段的生产接线和退出条件,架构现状文档才能更新
> **实现状态:分阶段交付。** 当前分支已完成共享 V2 应用契约、产品默认、旧偏好迁移、分页批量确认、Desktop/Peer/App Server 薄适配,以及 Desktop Settings 和交互式 TUI 的纵向切片。Web 在旧 Host 上保持严格 V1 只读回退;交互式 TUI 只在 Embedded 旧 Host 上回退 V1,未接线的 Shared Runtime 明确不支持且不会改在控制进程本地执行。通用 Server 尚未绑定可信 workspace owner,任务相关 `action-required`、非交互 CLI 结果、组合 Hook 摘要和完整跨宿主回归仍按本计划后续阶段推进,不能据此宣称支持

## 1. 目标与执行原则

Expand All @@ -19,7 +19,7 @@

- 每个阶段形成可独立评审的纵向结果,不能用仅有 DTO、固定假数据或未接线组件宣称完成;
- 先以测试冻结共享契约和策略,再接宿主,再替换信息架构;
- 当前 `ExternalSourceControlSnapshotV1`、V1 动作/恢复闭合枚举、V1 宿主能力和能力专属 DTO 保持字段与行为不变;应用级读写使用独立版本化 V2 接口,无副作用 V2 快照直接用于能力探测
- 当前 `ExternalSourceControlSnapshotV1`、V1 动作/恢复闭合枚举、V1 宿主能力和能力专属 DTO 保持字段与行为不变;应用级读写使用独立版本化 V2 接口,V2 快照不提交用户决定或运行能力写动作并直接用于能力探测;首次 owner 激活仍可执行可重入迁移和既有后台发现
- 所有 V2 写操作携带 `execution_domain_id`、`target_scope`、`operation_id` 和与该作用域绑定的 `expected_preference_revision`;`workspace_override` 必须携带宿主快照返回的 `workspace_scope_id`,`user_default` 必须省略。`operation_id` 只做请求/响应关联,不承诺幂等重放;偏好版本是唯一写并发保护;
- 宿主能力、Safe Mode、组织/产品安全上限和 Remote/只读限制只能收紧结果;
- React、TUI、Desktop 适配层和 Server 适配层不按生态 ID 重算默认连接、推荐集合或应用级状态;
Expand Down Expand Up @@ -81,7 +81,7 @@ P1-P4 是共享语义和协议前置;P5 与 P6 可以在 P4 稳定后并行,
- `enabled`、`pending_review`、`blocked`、`conflict` 数量;
- 风险摘要和恢复动作;
- 确认摘要、稳定 `review_id`、推荐数量/风险、`max_selection_count` 和总数,不内嵌项目列表或可执行载荷。
2. 另行定义 `ExternalApplicationReviewPageV2`:分页游标绑定执行域、工作区作用域、`review_id`、偏好版本和发现代次每页最多 128 项,只携带稳定项目引用、显示摘要、推荐和安全上限。读取分页不能触发重新发现或能力加载。
2. 另行定义 `ExternalApplicationReviewPageV2`:首次无 cursor/no-generation 打开允许 Host 在后台发现刚完成时返回当前只读计划,客户端从该响应接续;其余分页游标严格绑定执行域、工作区作用域、`review_id`、偏好版本和发现代次每页最多 128 项,只携带稳定项目引用、显示摘要、推荐和安全上限。读取分页不能触发重新发现或能力加载,提交仍必须绑定首次响应的权威计划
3. 将应用级状态优先级固定在共享归属模块:
`需要处理 > 暂时不可用 > 已连接 > 发现可用配置 > 未发现配置`;Safe Mode 独立投影。
4. 在 Product Assembly 中定义默认连接事实及原因:
Expand Down Expand Up @@ -258,6 +258,8 @@ cargo check --workspace
6. owner 可以逐项拒绝业务请求;响应必须返回每项 `applied / rejected / blocked / stale / failed` 等闭合结果及恢复动作,未知结果不得视为成功。
7. 只持久化实际成功且仍与 decision key/behavior version 匹配的决定;返回与最终 preference revision 同代的新快照。

这里的零应用保证止于分派前预检。分派开始后若某个 owner 的事实并发变化,响应可以同时包含已应用项与类型化 stale/failed 项;本阶段不增加跨 owner 事务或回滚管理器,也不宣称批量业务执行原子化。

### 测试优先顺序

- stale revision、generation 或 Host capability 导致整批零应用;
Expand Down Expand Up @@ -325,7 +327,7 @@ cargo check --workspace
- `interfaces/app-server-client` 与 TypeScript translation 保持 V1 wire shape,Server Host 绑定其真实 workspace,不读取浏览器或控制端路径;
- Server 不注册 write handler;未知/写方法在反序列化 mutation payload 前以 method-not-found/host-capability-unavailable 拒绝;
- 用真实 `/ws` transport 做 Server bootstrap → `BitfunAppServer::serve` → handler → owner → client 的端到端 round-trip。该切片通过前,Server 不进入 V2 共享 fixture,也不得标记为只读 external-source Host。
3. P4a 后新增无副作用 `get_external_application_snapshot_v2`,直接作为版本探测:成功响应必须是严格 V2 数据结构,并携带宿主读写能力;旧宿主的传输层 method-not-found 等价于“仅 V1”。不增加独立版本信息接口,也不引入“声明支持但接口不可用”的第二种状态。
3. P4a 后新增不提交用户决定或运行能力写动作的 `get_external_application_snapshot_v2`,直接作为版本探测:成功响应必须是严格 V2 数据结构,并携带宿主读写能力;首次 owner 激活可执行可重入迁移和既有后台发现,确认分页不得冷启动 owner。旧宿主的传输层 method-not-found 等价于“仅 V1”。不增加独立版本信息接口,也不引入“声明支持但接口不可用”的第二种状态。
4. 客户端只有在 V2 snapshot 校验成功后,才调用 `get_external_application_review_page_v2` 或 `apply_external_application_action_v2`。V2 snapshot/action 不与 V1 对象混合序列化;read-only Server 只登记 snapshot/review read endpoint,不登记 mutation endpoint。
5. Desktop Tauri command 只映射结构化 request/response,不派生状态、默认策略或推荐集合。
6. 每个新增 Desktop command 在 remote workspace policy 中声明明确策略;Remote 未支持时返回 V2 类型化 unsupported,不回退本机。
Expand Down Expand Up @@ -401,7 +403,7 @@ pnpm run type-check:web
3. 首页使用现有 `ConfigPageLayout` 的 760px 单列阅读轴:标题、应用列表、高级设置。真实的任务相关待办通过就地提示或状态变化处理,不把无法归属的系统诊断聚合成首页数量。
4. 每个应用行只显示应用名、一个状态、一句结果摘要和唯一主操作;有工作区时主操作明确标注“仅当前工作区”,没有工作区时先进入详情选择范围。来源路径、能力清单、冲突和诊断进入详情。
5. 详情按“结果优先、控制后置”排列;连接完成显示生效范围、已启用、待确认和受限摘要。`user_default` 只在详情/高级设置中提供,并在提交前再次展示会影响同一执行域的所有工作区。
6. 批量确认页面先使用快照摘要,再按需分页读取项目引用;按类别展示数量、主要风险、共享推荐状态和安全上限,技术详情按需展开,高风险默认未选。提交使用同代推荐/空集合基线和用户改动项,不为提交强制读取全部页面;首页轮询不读取项目页面。
6. 批量确认页面先使用快照摘要,再按需分页读取项目引用;默认只显示确认数量和“使用推荐/暂不启用”两个决定,单项名称、风险和安全上限放在折叠的调整区,不展示内部错误码、处理阶段或任意载荷。高风险默认未选。提交使用同代推荐/空集合基线和用户改动项,不为提交强制读取全部页面;首页轮询不读取项目页面。
7. Safe Mode 在首页和详情显著展示,高级设置保留现有 source、scope、冲突、诊断和能力级管理。
8. 首次发现只使用一次性轻提示和 Settings 导航状态;不增加启动 Modal 或常驻 banner。
9. 所有文案进入现有 i18n namespace,颜色与状态复用主题 token,不提高主题治理基线。
Expand Down
38 changes: 38 additions & 0 deletions scripts/core-boundaries/rules/source/public-api-rules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,8 @@ export const externalSourceContractPublicApiEntries = [

export const externalSourceControlPublicApiEntries = [
'EXTERNAL_SOURCE_CONTROL_SCHEMA_V1',
'EXTERNAL_APPLICATION_SCHEMA_V2',
'EXTERNAL_APPLICATION_REVIEW_PAGE_MAX_ITEMS',
'ExternalSourceOperationStage',
'ExternalSourceRecoveryActionV1',
'ExternalSourceDiscoveryState',
Expand All @@ -844,6 +846,39 @@ export const externalSourceControlPublicApiEntries = [
'ExternalSourceSurfaceSnapshotV1',
'ExternalSourceControlActionV1',
'ExternalSourceControlRequestV1',
'ExternalApplicationTargetScopeV2',
'ExternalApplicationDesiredConnectionV2',
'ExternalApplicationUserDecisionV2',
'ExternalApplicationDiscoveryStateV2',
'ExternalApplicationConnectionStateV2',
'ExternalApplicationHealthV2',
'ExternalApplicationEffectiveStatusV2',
'ExternalApplicationPrimaryActionV2',
'derive_external_application_status_v2',
'ExternalApplicationDefaultConnectionPolicyV2',
'ExternalApplicationRiskLevelV2',
'ExternalApplicationSafetyCeilingV2',
'ExternalApplicationRecoveryActionV2',
'ExternalApplicationHostCapabilitiesV2',
'ExternalApplicationRiskSummaryV2',
'ExternalApplicationReviewItemKindV2',
'ExternalApplicationReviewItemRefV2',
'ExternalApplicationOwnerGenerationV2',
'ExternalApplicationReviewCategoryCountV2',
'ExternalApplicationReviewRecommendationSummaryV2',
'ExternalApplicationReviewSummaryV2',
'ExternalApplicationSummaryV2',
'ExternalApplicationSnapshotV2',
'ExternalApplicationReviewItemV2',
'ExternalApplicationReviewPageRequestV2',
'ExternalApplicationReviewPageV2',
'ExternalApplicationReviewSelectionBaselineV2',
'ExternalApplicationReviewSelectionOverrideV2',
'ExternalApplicationControlActionV2',
'ExternalApplicationControlRequestV2',
'ExternalApplicationOperationOutcomeV2',
'ExternalApplicationReviewItemResultV2',
'ExternalApplicationControlResultV2',
].map((symbol) =>
externalSourceControlEntry(
symbol,
Expand Down Expand Up @@ -985,6 +1020,9 @@ export const externalSourceCorePublicApiEntries = [
'EXTERNAL_SOURCE_CONTROL_SCHEMA_V1',
'get_external_source_control_snapshot',
'apply_external_source_control_action',
'get_external_application_snapshot_v2',
'get_external_application_review_page_v2',
'apply_external_application_action_v2',
].map((symbol) =>
externalSourceControlEntry(
symbol,
Expand Down
9 changes: 9 additions & 0 deletions scripts/core-boundaries/self-test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1527,6 +1527,12 @@ export function runManifestParserSelfTest({
'ExternalSourceControlRequestV1',
'ExternalSourceOperationStage',
'ExternalSourceRecoveryActionV1',
'EXTERNAL_APPLICATION_SCHEMA_V2',
'ExternalApplicationSnapshotV2',
'ExternalApplicationReviewPageV2',
'ExternalApplicationControlActionV2',
'ExternalApplicationControlRequestV2',
'ExternalApplicationControlResultV2',
]) {
if (!externalSourceControlPublicApiRule?.allowedSymbolEntries.some(
(entry) => entry.symbol === requiredSymbol
Expand Down Expand Up @@ -1577,6 +1583,9 @@ export function runManifestParserSelfTest({
'ExternalSourceControlRequestV1',
'get_external_source_control_snapshot',
'apply_external_source_control_action',
'get_external_application_snapshot_v2',
'get_external_application_review_page_v2',
'apply_external_application_action_v2',
]) {
if (!externalSourceCorePublicApiRule?.allowedSymbolEntries.some(
(entry) => entry.symbol === requiredSymbol
Expand Down
Loading