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
10 changes: 8 additions & 2 deletions docs/architecture/agent-runtime-services-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Agent Runtime API 的逻辑归属与物理部署分离:相同归属模块可
私有 SDK Host 或目标机器 Runtime 中。任何 Rust 部署都只管理自己进程树内的服务与 Node/Bun Plugin Host;不能因为多个
GUI/TUI/Remote Client 连接就复制 Runtime 状态模块,或按 Client/Workspace 创建 Plugin Host。

Rust Runtime SDK 以 `AGENT_RUNTIME_SDK_API_VERSION` 标记兼容边界。当前接口版本为 v5 preview:
Rust Runtime SDK 以 `AGENT_RUNTIME_SDK_API_VERSION` 标记兼容边界。当前接口版本为 v6 preview:
小版本更新允许增加可选 builder hook、有默认实现的端口方法或注册表查询能力,但不得向外部可用
Rust 结构体字面量(struct literal)构造的 DTO 直接增加字段,也不得改变既有端口语义、错误分类、session / turn 标识含义或
默认 feature 依赖。任何需要调用方改写现有嵌入代码的变更,必须提升接口版本并提供兼容迁移路径。
Expand All @@ -83,6 +83,12 @@ v3 为 `AgentDialogTurnRequest` 增加来源无关的 `execution` 事实。现
v4 将活动 Turn 的文本 steer 纳入 `AgentDialogTurnPort`,复用同一个 Runtime owner 和精确 Session/Turn
身份校验;默认端口实现仍返回 `NotAvailable`,未选择该能力的 provider 不需要建立第二套 queue 或 transport。

v6 将完整 Rust Runtime SDK 从空默认编译面移入 `agent-runtime` owner feature。现有 Rust embedder
迁移时在 `bitfun-agent-runtime` 依赖上显式选择 `features = ["agent-runtime"]`;启用后 `sdk` 模块、
公开路径和运行时行为保持不变。只消费 DeepResearch 编号或 Hook 设置的调用方应分别选择
`deep-research` 或 `native-hook-settings`,不需要继承完整 Runtime。仓库内最小 SDK example 通过
`required-features = ["agent-runtime"]` 明确记录这一版本边界。

只要外部调用方仍必须导入 `bitfun-core`、启用 `product-full`、持有具体服务管理器、读取产品命令
注册表、理解 ACP/内部端口或依赖全局可变状态,公开 SDK 发布边界就不成立。公开 SDK 的完整
术语、能力等价和版本要求以 [`agent-sdk-product-architecture.md`](agent-sdk-product-architecture.md) 为准。
Expand Down Expand Up @@ -426,7 +432,7 @@ impl AgentRuntime {
该 Rust 接口是内部产品入口复用的当前形态,不是公开 Python/TypeScript SDK 的目标 API。它必须只接收
已组装的类型化部件,不负责创建
文件系统、终端、MCP、AI 客户端、Remote 提供方或产品命令。
当前 v4 preview 接口以 message / attachment / metadata、默认标准执行目标和活动 Turn 文本 steer 作为最小输入形态;若把
当前 v6 preview 接口以 message / attachment / metadata、默认标准执行目标和活动 Turn 文本 steer 作为最小输入形态;若把
model-round cancellation token、结构化 AgentInput 或更复杂的事件游标纳入公开 SDK,
必须分别评审 Rust Runtime SDK、SDK Host protocol 和公开 SDK API 的版本,并保留旧路径兼容。

Expand Down
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 @@ -213,7 +213,7 @@ CLI 只消费 typed summary 与 typed action:
| 变更范围 | 最小验证 |
| --- | --- |
| TUI state/input/render | focused reducer/input/render test + `cargo test -p bitfun-cli` |
| Agent Runtime SDK/port | `cargo test -p bitfun-agent-runtime` + owner focused test |
| Agent Runtime SDK/port | `cargo test -p bitfun-agent-runtime --no-default-features --features agent-runtime --lib` + owner focused test |
| Shared IPC | protocol round-trip、controller/idle、timeout/outcome-unknown、disconnect cancel |
| Core turn/tool | 权限 allow/ask/deny、取消、事件、上下文、持久化恢复 |
| `exec` output | stdout/stderr、单一最终状态、session conflict、Ctrl+C、Patch |
Expand Down
2 changes: 2 additions & 0 deletions docs/architecture/rust-build-dependency-boundaries.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ Core library 的默认 feature 集合为空;完整产品必须显式选择 `pr

Core 的 `agent-runtime` 只承载 Agent 生命周期基线和明确的基线工具,不得再次把 MCP、Remote Connect、模型目录、Browser/Web、Git/LSP 或产品工具组藏成 capability union。具体 service 由同名 owner feature 选择,内置工具由 `tools-*` 选择;`product-full` 显式相加全部 owner,CLI/ACP 等窄入口则按真实命令与构造路径列出自己的闭包。

执行层的 `bitfun-agent-runtime` 自身也保持空默认:完整生命周期由 `agent-runtime` 选择,DeepResearch 纯编号由 `deep-research` 选择,原生 Hook 配置解析与进程执行分别由 `native-hook-settings`、`native-hook-runtime` 选择。叶能力仍留在原 owner crate 内,不为依赖收敛新建 DTO/runtime crate;完整产品必须显式恢复真实 owner,不能依赖 workspace feature union 偶然补齐。

Owner feature 不等于“无前置依赖”。当实现确实调用较低层基线时,依赖必须按 `owner → baseline` 显式组合,禁止反向把 owner 藏回基线:例如 Core MCP 工具桥和 Remote Connect 依赖 Agent 生命周期,Workspace Search 依赖本地 Workspace Runtime。每个新增或调整后的 owner 闭包都必须单独 `cargo check`,避免被 Desktop/CLI 的 feature union 偶然补齐。

只为已经启用的 optional dependency 增加子能力时,使用 Cargo 的弱依赖转发
Expand Down
37 changes: 36 additions & 1 deletion docs/performance/01-compile-performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,41 @@ Clap、Tracing Subscriber、Notify 等默认即产品契约或缺少独立收益

重复版本数量只用于发现候选,不能直接转化为治理任务。`oxc`、`rquickjs`、vendored `git2`、`sherpa-onnx` 等重依赖都有真实 capability owner;只有某个产品入口不消费对应能力时,才允许让它退出该入口的构建图。

以下以 `gcwing/main@d1d1dd9e8` 为变更前基线,把 `bitfun-agent-runtime` 内部长期共存的完整 Runtime、
DeepResearch 纯编号和原生 Hook 配置/执行拆成同 crate 的 owner feature。没有新增 crate 或兼容 `full`
umbrella;统计仍按三个既定 target triple、`normal,build` 版本化 package instance 去重:

| 闭包 | Windows | macOS | Linux | 边界结果 |
|---|---:|---:|---:|---|
| Agent Runtime feature-free | 76 → 1 | 79 → 1 | 78 → 1 | 空默认只保留 crate 本身;所有运行时源码和第三方依赖由 owner feature 选择 |
| Agent Runtime `agent-runtime` | 76 → 76 | 79 → 79 | 78 → 78 | 完整 Runtime API、Hook 执行和依赖闭包保持不变 |
| Agent Runtime `native-hook-settings` | 76 → 10 | 79 → 10 | 78 → 10 | Hook 配置解析不再编译进程执行、Session、Tool 和 Runtime Services |
| Services Integrations `deep-research` | 77 → 36 | 80 → 38 | 79 → 37 | 只保留纯编号、WorkspaceFS port 与报告 IO;完整 Agent Runtime 退出 |
| Services Integrations `hook-import` | 121 → 89 | 112 → 79 | 111 → 78 | 只复用 Hook settings contract;Session/Agent lifecycle 退出 |
| Core `product-full` | 569 → 569 | 556 → 556 | 600 → 600 | 完整产品显式恢复全部真实 owner,package 闭包不缩水 |

测试闭包也按真实 owner 收敛:Agent Runtime 的 DeepResearch target 在 `normal,build,dev` 口径从
`76/79/78` 降到 `6/6/6`,Hook settings target 降到 `10/10/10`;Services DeepResearch 测试从
`80/85/85` 降到 `44/48/47`。为保持 feature 与进程失败域,Agent Runtime 显式 integration target 从
5 个增为 7 个:DeepResearch 与 Hook settings 各自独立,Unix Hook 子进程测试继续独立;没有把这些
focused target 加进 CI,也没有新增 job、矩阵或仓库级命令。

该轮同时修复 DeepResearch post-turn IO 的既有远程路径错误:Core 现在把当前 session 注入的
`WorkspaceFileSystem` 传给 Services Integrations,本地和 Remote SSH 都通过同一 provider 读取报告、
引用表并写回 sidecar;远程逻辑路径不再被 Windows host 当成本机 `Path` 探测。provider 缺失时明确
跳过并记录 warning,不允许回退到宿主文件系统。纯编号算法、报告内容、sidecar schema 和本地
best-effort 行为保持不变。路径拼接语义也由 `WorkspaceFileSystem` provider 持有:本地 provider
继承宿主路径规则,Remote SSH 对绝对、home 和相对 workspace root 均保持 POSIX 分隔符。

`bitfun-services-integrations::deep_research::run_for_session_workspace` 与
`try_renumber_research_report` 的公开函数签名现在要求显式传入 `WorkspaceFileSystem`;仓内唯一生产
调用者已迁移。这是为消除远程路径宿主回退而做的有意源码契约收紧,不能描述为对未知的仓外 path/git
consumer 零影响。完整 Rust Runtime SDK 同时将兼容版本提升为 v6:仓外 embedder 需要在
`bitfun-agent-runtime` 依赖上显式选择 `agent-runtime`;启用后原 `sdk` 公开路径和行为保持不变。

这里仍只报告依赖图和 focused-test 输入,不宣称完整产品 wall-clock 提速。根 `Cargo.lock` package
集合与字节均不变,新增/升级/降级 package 为 0;`.github` 和 `ci.yml` 不变。

### 3.3 CI 与本地验证

- 现有 CI 已覆盖 workspace check、Core/Desktop lib、平台敏感 owner 测试和独立 runtime/CLI 验证;本轮不新增 job、矩阵或 changed-path 分类器。
Expand All @@ -340,7 +375,7 @@ Clap、Tracing Subscriber、Notify 等默认即产品契约或缺少独立收益
| 重型可选能力 | 文档转换和本地订阅凭据由弱 modifier 细化已有 runtime owner;Core 基线和 App Server 退出未消费闭包 |
| Installer 闭包 | 删除 8 个未使用直接 dependency;独立 workspace 和发布生命周期不变,本 PR 不提交其生成 lockfile |
| SDK Host 闭包 | 从 `product-full` 改为与当前协议/构造路径一致的显式 Core owner closure;保留 ring TLS 初始化,本机 SDK 行为不变,未交付的远程执行能力不再进入构建图 |
| Agent Runtime 测试 | 28 个 integration executable 已收敛为 5 个职责/平台 target |
| Agent Runtime 测试 | 28 个 integration executable 已完成职责聚合;当前 7 个 target 中,DeepResearch、Hook settings 与 Hook 子进程按 feature/进程失败域独立,其余保持聚合 |
| Services 测试 | 两个服务 crate 使用显式 target;选中闭包少 8 个 integration executable,进程/feature/external-system 边界保持独立 |
| External Sources 测试 | 四个 adapter/assembly crate 从 22 个 target 收敛到 7 个;MCP、插件服务和脚本 runtime 继续独立 |
| Contracts/AI/Assembly 测试 | 五个 crate 从 28 个 target 收敛到 10 个;AI loopback 与纯协议、Product Domains 各 owner feature 保持独立 |
Expand Down
4 changes: 2 additions & 2 deletions docs/plans/core-decomposition-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
| CLI / Desktop / ACP | CLI 与 ACP 已分别提交对应 `DeliveryProfile`、消费 Runtime Parts/SDK,并选择经过评审的 Core owner feature closure;Desktop 仍启用 `bitfun-core/product-full`,主交互已消费由现有 owner 构造的窄口径 SDK 接口 | 三个入口仍复用单一 Core runtime owner;完整 Desktop profile 和剩余兼容操作仍需逐项迁移 |
| Server | 当前生产路由只形成 health/info/ping 基线 | 没有插件状态或独立产品组装完整流程 |
| Server / Remote / Web / Mobile Web / SDK profile | 当前为空计划、未接入入口或仅有 preview 测试 | 不得据枚举值宣称产品能力已交付 |
| Agent Runtime SDK | 已有无 `bitfun-core` 依赖的 v3 preview 接口和 smoke test | 发布边界仍需真实嵌入方证明 |
| Agent Runtime SDK | 已有无 `bitfun-core` 依赖的 v6 preview 接口和 smoke test | 发布边界仍需真实嵌入方证明 |
| 插件运行时 | 现有路径只覆盖 BitFun 原生包和 OpenCode custom tool 静态名称预览 | 不能据通用消息结构或静态候选扩张稳定 ABI |
| Relay | room/device 状态、account/sync 存储、asset store 与 HTTP/WebSocket router 已归属 `services/relay-service`,standalone 与 embedded 入口同向消费;embedded bind、静态 fallback 和任务生命周期由 Desktop 窄宿主端口持有 | Cargo metadata 门禁覆盖 workspace、独立 manifest、normal/build/dev 依赖及 optional/target 变体;宿主归位已完成并由生命周期与边界测试保护 |
| CLI CI | 独立 Linux job 运行 CLI test,通用三平台 workspace check 覆盖 CLI 编译;Linux PTY 与 Windows ConPTY 有启动页生命周期及本地确定性流式模型夹具驱动的活动 turn 进程测试,发布归档上传前校验 SHA-256 并解压执行 | 参数/序列化/前置失败和组装已有 focused contract;本地模型 HTTP 403 授权拒绝、流中断后的重试失败、Linux PTY/Windows ConPTY Chat resize/取消、`exec` Ctrl+C 及 Patch I/O 失败已有分层回归,真实供应商审批交互、macOS 活动 PTY 与 OS 级终端故障注入仍需补齐 |
Expand Down Expand Up @@ -129,7 +129,7 @@ Core 只为插件兼容提供已有 owner 的窄接口:真实工具、类型
| 文档与仓库边界 | `pnpm run check:repo-hygiene`,`node --test scripts/check-core-boundaries.test.mjs`,`node scripts/check-core-boundaries.mjs` |
| 入口 profile 迁移 | 对应 app 的 check/test、入口级 smoke、profile/服务可用性断言、旧路径等价用例 |
| Relay 共享 owner / Cargo 方向 | standalone 与 embedded focused tests、Cargo 依赖方向失败用例、Desktop 宿主启停/失败回滚/静态缓存行为测试 |
| Agent Runtime / SDK | `cargo test -p bitfun-agent-runtime`,最小 no-`bitfun-core` 嵌入测试 |
| Agent Runtime / SDK | `cargo test -p bitfun-agent-runtime --no-default-features --features agent-runtime --lib`,最小 no-`bitfun-core` 嵌入测试 |
| 插件首个执行切片 | runtime ports、`PluginRuntimeClient`、生态 adapter、`ScriptToolRuntime`、Plugin Host 与真实固定 fixture 的端到端调用 |
| CLI | `cargo check -p bitfun-cli`,`cargo test -p bitfun-cli`,结构化协议和 package smoke |

Expand Down
70 changes: 65 additions & 5 deletions scripts/check-core-boundaries.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,15 @@ import {
capabilityContractDependencyRules,
coreClosedFeatureProfileRules,
coreProductFullFeatureAssemblyRule,
guardedEmptyInternalDefaultManifestPaths,
optionalDependencyFeatureOwnerRules,
} from './core-boundaries/rules/feature-rules.mjs';
import {
agentRuntimeRootPublicModules,
forbiddenContentRules,
publicApiAllowlistRules,
requiredContentRules,
} from './core-boundaries/rules/source-rules.mjs';

const ENTRYPOINT = new URL('./check-core-boundaries.mjs', import.meta.url);
const MODULES = [
Expand All @@ -57,6 +64,59 @@ const MODULES = [

const TEST_ROOT = join('C:', 'repo');

test('Agent Runtime leaf capabilities have one managed feature and source contract', async () => {
const rule = capabilityContractDependencyRules.find(
(candidate) => candidate.packageName === 'bitfun-agent-runtime',
);
assert.ok(rule, 'bitfun-agent-runtime must be a managed capability target');
assert.deepEqual(Object.keys(rule.featureProfiles).sort(), [
'agent-runtime',
'deep-research',
'default',
'native-hook-runtime',
'native-hook-settings',
]);
assert.equal(rule.consumers.size, 10);
assert.ok(
guardedEmptyInternalDefaultManifestPaths.includes(
'src/crates/execution/agent-runtime/Cargo.toml',
),
);
assert.ok(requiredContentRules.some(
(sourceRule) => sourceRule.path === 'src/crates/execution/agent-runtime/src/lib.rs'
&& sourceRule.reason.includes('leaf capability modules'),
));
const publicApiRule = publicApiAllowlistRules.find(
(sourceRule) => sourceRule.path === 'src/crates/execution/agent-runtime/src/lib.rs',
);
assert.ok(publicApiRule, 'bitfun-agent-runtime root must have a closed public module allowlist');
assert.deepEqual(
new Set(publicApiRule.allowedSymbols),
new Set(agentRuntimeRootPublicModules),
);
const flatRootRule = forbiddenContentRules.find(
(sourceRule) => sourceRule.path === 'src/crates/execution/agent-runtime/src/lib.rs'
&& sourceRule.reason.includes('flat feature-owned module wrapper'),
);
assert.ok(flatRootRule, 'bitfun-agent-runtime root must reject non-wrapper source lines');
const rootSource = await readFile(
new URL('../src/crates/execution/agent-runtime/src/lib.rs', import.meta.url),
'utf8',
);
assert.equal(flatRootRule.patterns[0].regex.test(rootSource), false);
for (const mutation of [
'#[doc(hidden)] pub mod accidental_feature_free_api;',
'pub union AccidentalFeatureFreeApi { value: u64 }',
'const DOC: &str = "{";\npub mod accidental_feature_free_api;',
]) {
assert.equal(
flatRootRule.patterns[0].regex.test(`${rootSource}\n${mutation}`),
true,
`Agent Runtime root must reject mutation: ${mutation}`,
);
}
});

test('Core and ACP defaults preserve their explicit assembly contracts', async () => {
const [coreManifest, acpManifest] = await Promise.all([
readFile(new URL('../src/crates/assembly/core/Cargo.toml', import.meta.url), 'utf8'),
Expand Down Expand Up @@ -3586,11 +3646,11 @@ test('unreviewed consumers cannot add capability contract dependency edges', asy
],
);

const messages = findTestCapabilityViolations(findCapabilityContractConsumerViolations, [
runtimePorts,
agentTools,
unreviewed,
]).map(
const messages = findTestCapabilityViolations(
findCapabilityContractConsumerViolations,
[runtimePorts, agentTools, unreviewed],
capabilityContractDependencyRules.slice(0, 2),
).map(
(violation) => violation.message,
);
assert.equal(messages.length, 1, messages.join('\n'));
Expand Down
16 changes: 15 additions & 1 deletion scripts/core-boundaries/cargo-dependency-boundaries.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ const SERVICES_INTEGRATIONS_TOKIO_FEATURES = new Map([
['browser-control', ['time']],
['canvas-runtime', ['fs']],
['debug-log', ['rt']],
['deep-research', ['fs']],
['deep-research', []],
['git', ['fs', 'io-util', 'macros', 'rt', 'time']],
['file-watch', ['rt', 'sync']],
['function-agents', ['fs', 'io-util', 'macros', 'rt', 'time']],
Expand Down Expand Up @@ -181,6 +181,10 @@ const CORE_TOKIO_AGGREGATES = new Set([
'tools-browser-web',
'tools-mcp',
]);
const AGENT_RUNTIME_TOKIO_FEATURES = new Map([
['native-hook-runtime', ['io-util', 'macros', 'process', 'rt', 'time']],
['agent-runtime', ['io-util', 'macros', 'process', 'rt', 'sync', 'time']],
]);

const TOKIO_DEPENDENCY_POLICY_EXCLUDED_PACKAGES = new Set();

Expand Down Expand Up @@ -720,10 +724,14 @@ export function findTokioDependencyFeatureViolations(packages) {
const featureOwnedCoreRuntime =
pkg.name === 'bitfun-core'
&& (dependency.kind ?? null) === null;
const featureOwnedAgentRuntime =
pkg.name === 'bitfun-agent-runtime'
&& (dependency.kind ?? null) === null;
if (
featureOwnedIntegrationRuntime
|| featureOwnedServicesCoreRuntime
|| featureOwnedCoreRuntime
|| featureOwnedAgentRuntime
) {
const actual = [...features].sort();
const expected = [...(featureOwnedCoreRuntime
Expand Down Expand Up @@ -767,6 +775,12 @@ export function findTokioDependencyFeatureViolations(packages) {
CORE_TOKIO_AGGREGATES,
));
}
if (pkg.name === 'bitfun-agent-runtime') {
violations.push(...findOwnedTokioFeatureViolations(
pkg,
AGENT_RUNTIME_TOKIO_FEATURES,
));
}
}

return violations;
Expand Down
Loading