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
3 changes: 3 additions & 0 deletions docs/architecture/agent-runtime-services-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -717,12 +717,15 @@ product-assembly

```rust
pub enum DeliveryProfile {
ProductFull,
Desktop,
Cli,
Server,
Remote,
Acp,
Web,
MobileWeb,
Sdk,
}

pub struct CapabilitySet {
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/core-decomposition.md
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ Platform adapter 只实现 ports 并调用边界外资源。

| 接口 / API | 定义 owner | 实现 owner | 注册者 | 消费者 | 边界 |
|---|---|---|---|---|---|
| `ProductAssembler` / `ProductAssemblyPlan` | Product Assembly | 产品入口或 assembly crate | 产品入口 | Desktop / CLI / Web / SDK / ACP | 选择能力,不写 Agent 状态机 |
| `ProductAssembler` / `ProductAssemblyPlan` | Product Assembly | 产品入口或 assembly crate | 产品入口 | Desktop / CLI / Server / Remote / Web / Mobile Web / SDK / ACP | 选择能力,不写 Agent 状态机 |
| `ProductFeaturePack` | Product Feature | feature owner | Product Assembly | 产品入口、Kernel API、UI host | 编排 feature,不拥有 OS concrete 或 Extension Host |
| `AgentRuntimeBuilder` / Kernel API | Agent Kernel | `bitfun-agent-runtime` | Product Assembly / SDK host | Product Feature、SDK、Extension adapter | 接收 typed parts,不创建 concrete manager |
| `ToolRuntimeBuilder` / Tool contracts | Execution | tool/execution owner | Product Assembly | Agent Kernel 通过 execution port、Harness | 执行 tool,不选择产品形态 |
Expand Down
6 changes: 6 additions & 0 deletions docs/plans/core-decomposition-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@

### PR-E:Cross-platform Adapter 与多形态 SDK 验证

状态:已完成本轮 SDK / 产品组装验证收口。

- `ProductRuntimeParts` 支持所有权交接到 runtime builder 输入。
- `bitfun-product-capabilities` 覆盖 SDK no-direct-core profile 和 product-full 兼容 profile 组装到 `AgentRuntimeBuilder` 的无 `bitfun-core` smoke。
- agent-runtime crate 级规则禁止 product assembly、concrete tool runtime 和平台/provider concrete 依赖回流。

目标:

- 收口 filesystem、network、process/thread/time、terminal、remote、Git、MCP transport、AI/provider protocol、browser/desktop automation 的 adapter/provider 边界。
Expand Down
6 changes: 6 additions & 0 deletions scripts/core-boundaries/rules/crate-rules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,11 @@ export const lightweightBoundaryRules = [
'bitfun-services-core',
'bitfun-services-integrations',
'bitfun-tool-packs',
'bitfun-product-capabilities',
'bitfun-product-domains',
'bitfun-transport',
'terminal-core',
'tool-runtime',
'tauri',
'reqwest',
'git2',
Expand All @@ -143,9 +145,11 @@ export const lightweightBoundaryRules = [
'bitfun-services-core',
'bitfun-services-integrations',
'bitfun-tool-packs',
'bitfun-product-capabilities',
'bitfun-product-domains',
'bitfun-transport',
'terminal-core',
'tool-runtime',
'tauri',
'reqwest',
'git2',
Expand Down Expand Up @@ -353,9 +357,11 @@ export const dependencyProfileRules = [
'bitfun-services-core',
'bitfun-services-integrations',
'bitfun-tool-packs',
'bitfun-product-capabilities',
'bitfun-product-domains',
'bitfun-transport',
'terminal-core',
'tool-runtime',
'tauri',
'reqwest',
'git2',
Expand Down
52 changes: 52 additions & 0 deletions scripts/core-boundaries/rules/source/forbidden-rules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,58 @@ export const forbiddenContentRules = [
},
],
},
{
path: 'src/crates/execution/agent-runtime/src/sdk.rs',
patterns: [
{
regex: /\bbitfun_core\b/,
message: 'SDK facade must not expose bitfun-core',
},
{
regex: /\bbitfun_product_capabilities\b/,
message: 'SDK facade must not expose product assembly facts',
},
{
regex: /\btauri\b/,
message: 'SDK facade must not expose Tauri APIs',
},
{
regex: /\bAppHandle\b/,
message: 'SDK facade must not expose desktop app handles',
},
{
regex: /\breqwest\b/,
message: 'SDK facade must not expose concrete HTTP clients',
},
{
regex: /\bgit2\b/,
message: 'SDK facade must not expose concrete Git providers',
},
{
regex: /\brmcp\b/,
message: 'SDK facade must not expose concrete MCP clients',
},
],
},
{
path: 'src/crates/assembly/product-capabilities/tests/product_sdk_assembly.rs',
patterns: [
{
regex: /\bbitfun_core\b/,
message:
'product assembly to SDK smoke must not depend on bitfun-core',
},
{
regex: /\bCoreRuntimeServicesProvider\b/,
message:
'product assembly to SDK smoke must not use core concrete service adapters',
},
{
regex: /\btauri\b/,
message: 'product assembly to SDK smoke must not depend on Tauri',
},
],
},
{
path: 'src/crates/contracts/core-types/src/ai.rs',
patterns: [
Expand Down
52 changes: 52 additions & 0 deletions scripts/core-boundaries/rules/source/required-rules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,10 @@ export const requiredContentRules = [
regex: /\bMobileWeb\b/,
message: 'missing mobile web delivery profile coverage',
},
{
regex: /\bDeliveryProfile::Sdk\b/,
message: 'missing SDK delivery profile coverage',
},
{
regex: /\bProductAssembler\b/,
message: 'missing typed product assembler',
Expand All @@ -1094,6 +1098,10 @@ export const requiredContentRules = [
regex: /\bProductRuntimeParts\b/,
message: 'missing product runtime parts output',
},
{
regex: /\binto_runtime_parts\b/,
message: 'missing owned runtime-parts handoff for SDK/product assembly consumers',
},
{
regex: /\bfeature_groups_from_tool_provider_group_plan\b/,
message: 'missing tool-provider feature group projection owner',
Expand Down Expand Up @@ -1131,6 +1139,42 @@ export const requiredContentRules = [
},
],
},
{
path: 'src/crates/assembly/product-capabilities/tests/product_sdk_assembly.rs',
reason:
'product-capabilities must prove product runtime parts can feed the SDK runtime without bitfun-core',
patterns: [
{
regex: /\bproduct_runtime_parts_can_build_agent_runtime_sdk_without_core\b/,
message: 'missing product assembly to SDK runtime smoke',
},
{
regex:
/\bsdk_delivery_profile_builds_minimal_agent_runtime_without_product_full_capabilities\b/,
message: 'missing SDK delivery profile minimal runtime smoke',
},
{
regex: /\bProductAssembler::new\(\)/,
message: 'product SDK smoke must assemble through ProductAssembler',
},
{
regex: /\binto_runtime_parts\b/,
message: 'product SDK smoke must consume owned ProductRuntimeParts',
},
{
regex: /\bAgentRuntimeBuilder::new\(\)/,
message: 'product SDK smoke must build through the Agent Runtime SDK facade',
},
{
regex: /\bDeliveryProfile::Cli\b/,
message: 'product SDK smoke must cover a product-full compatibility delivery profile',
},
{
regex: /\bDeliveryProfile::Sdk\b/,
message: 'product SDK smoke must cover the no-direct-core SDK delivery profile',
},
],
},
{
path: 'src/crates/execution/agent-runtime/src/agents.rs',
reason:
Expand Down Expand Up @@ -6033,6 +6077,14 @@ export const requiredContentRules = [
regex: /\bproduct_tool_runtime_registry_preserves_provider_plan_order\b/,
message: 'missing product tool provider plan-to-registry order regression',
},
{
regex: /\bproduct_tool_runtime_keeps_no_direct_core_profiles_empty\b/,
message: 'missing no-direct-core product tool runtime regression',
},
{
regex: /\bDeliveryProfile::Sdk\b/,
message: 'product tool runtime no-direct-core regression must cover SDK profile',
},
],
},
{
Expand Down
25 changes: 25 additions & 0 deletions scripts/core-boundaries/self-test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -674,12 +674,24 @@ export function runManifestParserSelfTest({
if (!agentRuntimeRule?.forbiddenDeps.includes('bitfun-services-integrations')) {
throw new Error('agent-runtime lightweight boundary must forbid concrete service integrations');
}
if (!agentRuntimeRule?.forbiddenDeps.includes('bitfun-product-capabilities')) {
throw new Error('agent-runtime lightweight boundary must forbid product assembly facts');
}
if (!agentRuntimeRule?.forbiddenDeps.includes('tool-runtime')) {
throw new Error('agent-runtime lightweight boundary must forbid concrete tool runtime');
}
const agentRuntimeProfile = dependencyProfileRules.find(
(rule) => rule.crateName === 'agent-runtime',
);
if (!agentRuntimeProfile?.forbiddenNonOptionalDeps.includes('tauri')) {
throw new Error('agent-runtime dependency profile must forbid product surface dependencies');
}
if (!agentRuntimeProfile?.forbiddenNonOptionalDeps.includes('bitfun-product-capabilities')) {
throw new Error('agent-runtime dependency profile must forbid product assembly facts');
}
if (!agentRuntimeProfile?.forbiddenNonOptionalDeps.includes('tool-runtime')) {
throw new Error('agent-runtime dependency profile must forbid concrete tool runtime');
}
const productCapabilitiesRule = lightweightBoundaryRules.find(
(rule) => rule.crateName === 'product-capabilities',
);
Expand Down Expand Up @@ -1708,6 +1720,8 @@ export function runManifestParserSelfTest({
'ProductCapabilityAssembly',
'ProductFeatureGroup',
'ProductRuntimeAssembly',
'DeliveryProfile::Sdk',
'into_runtime_parts',
'feature_groups_from_tool_provider_group_plan',
],
},
Expand All @@ -1719,6 +1733,15 @@ export function runManifestParserSelfTest({
'product_harness_provider_plans_legacy_facade_without_execution',
],
},
{
path: 'src/crates/assembly/product-capabilities/tests/product_sdk_assembly.rs',
contracts: [
'product_runtime_parts_can_build_agent_runtime_sdk_without_core',
'sdk_delivery_profile_builds_minimal_agent_runtime_without_product_full_capabilities',
'DeliveryProfile::Cli',
'DeliveryProfile::Sdk',
],
},
{
path: 'src/crates/assembly/core/src/agentic/tools/pipeline/tool_pipeline.rs',
contracts: [
Expand Down Expand Up @@ -2232,6 +2255,8 @@ export function runManifestParserSelfTest({
'product_assembly_plan_for_profile',
'product_tool_runtime_owner_preserves_registry_contract',
'product_tool_runtime_registry_preserves_provider_plan_order',
'product_tool_runtime_keeps_no_direct_core_profiles_empty',
'DeliveryProfile::Sdk',
],
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ mod tests {
DeliveryProfile::Remote,
DeliveryProfile::Web,
DeliveryProfile::MobileWeb,
DeliveryProfile::Sdk,
] {
let runtime = ProductToolRuntime::for_profile(profile);
let registry = runtime.create_registry();
Expand Down
2 changes: 2 additions & 0 deletions src/crates/assembly/product-capabilities/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ bitfun-runtime-services = { path = "../../execution/runtime-services" }
bitfun-tool-packs = { path = "../../execution/tool-provider-groups", default-features = false }

[dev-dependencies]
async-trait = { workspace = true }
bitfun-agent-runtime = { path = "../../execution/agent-runtime" }
tokio = { workspace = true }
17 changes: 14 additions & 3 deletions src/crates/assembly/product-capabilities/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ pub enum DeliveryProfile {
Acp,
Web,
MobileWeb,
Sdk,
}

impl DeliveryProfile {
Expand All @@ -155,6 +156,7 @@ impl DeliveryProfile {
Self::Acp => "acp",
Self::Web => "web",
Self::MobileWeb => "mobile-web",
Self::Sdk => "sdk",
}
}

Expand All @@ -168,6 +170,7 @@ impl DeliveryProfile {
Self::Acp,
Self::Web,
Self::MobileWeb,
Self::Sdk,
]
}
}
Expand Down Expand Up @@ -244,6 +247,10 @@ const PRODUCT_DELIVERY_PROFILE_ENTRIES: &[ProductDeliveryProfileEntry] = &[
DeliveryProfile::MobileWeb,
ProductCoreDependencyMode::NoDirectCoreDependency,
),
ProductDeliveryProfileEntry::new(
DeliveryProfile::Sdk,
ProductCoreDependencyMode::NoDirectCoreDependency,
),
];

pub const fn product_delivery_profile_entries() -> &'static [ProductDeliveryProfileEntry] {
Expand Down Expand Up @@ -493,6 +500,11 @@ impl ProductRuntimeParts {
pub fn missing_service_requirements(&self) -> &[ProductServiceCapabilityRequirement] {
&self.missing_service_requirements
}

/// Consume the assembled product output into runtime-builder inputs.
pub fn into_runtime_parts(self) -> (RuntimeServices, HarnessRegistry) {
(self.services, self.harness_registry)
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -927,8 +939,7 @@ fn product_capability_registry_for_profile(profile: DeliveryProfile) -> ProductC
DeliveryProfile::Server
| DeliveryProfile::Remote
| DeliveryProfile::Web
| DeliveryProfile::MobileWeb => {
ProductCapabilityRegistry::new(EMPTY_PRODUCT_CAPABILITY_PACKS)
}
| DeliveryProfile::MobileWeb
| DeliveryProfile::Sdk => ProductCapabilityRegistry::new(EMPTY_PRODUCT_CAPABILITY_PACKS),
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ fn no_direct_core_profiles_do_not_select_product_full_runtime_capabilities() {
DeliveryProfile::Remote,
DeliveryProfile::Web,
DeliveryProfile::MobileWeb,
DeliveryProfile::Sdk,
] {
let plan = product_assembly_plan_for_profile(profile);

Expand Down Expand Up @@ -277,6 +278,10 @@ fn product_delivery_profile_matrix_documents_current_core_dependency_shape() {
DeliveryProfile::MobileWeb,
ProductCoreDependencyMode::NoDirectCoreDependency,
),
(
DeliveryProfile::Sdk,
ProductCoreDependencyMode::NoDirectCoreDependency,
),
]
);
assert_eq!(
Expand Down Expand Up @@ -509,6 +514,7 @@ fn product_assembler_allows_no_direct_core_profiles_without_product_services() {
DeliveryProfile::Remote,
DeliveryProfile::Web,
DeliveryProfile::MobileWeb,
DeliveryProfile::Sdk,
] {
let services = FakeRuntimeServicesProvider::with_all_required()
.build_services()
Expand Down
Loading
Loading