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
17 changes: 14 additions & 3 deletions docs/plans/core-decomposition-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -1076,10 +1076,13 @@ pub fn create_tool_registry() -> ToolRegistry {
- [x] runtime manifest assembly / `GetToolSpec` 执行迁移前的 baseline 已作为 H1 进入条件:
保留并扩展 expanded/collapsed manifest、
prompt-visible stub、unlock state 和 desktop/MCP/ACP catalog 等价测试。
- [x] H1 解锁契约切片只抽出 `GetToolSpec` 结果到 collapsed 工具名集合的纯收集规则;
`ToolUseContext.unlocked_collapsed_tools`、执行消息解析、runtime manifest assembly 和
`GetToolSpecTool` 执行仍由 core 拥有。

**当前安全迁移状态(2026-05-18):**

- 已迁移到 `bitfun-agent-tools`:`ToolResult`、`ValidationResult`、`InputValidator`、dynamic tool metadata、tool render options、runtime restriction DTO、path resolution DTO、`ToolContextFacts` / `ToolWorkspaceKind` 轻量上下文事实、`PortableToolContextProvider` 只读 facts provider、不依赖 core service 的 `ToolRegistry<T>` / `ToolRegistryItem` generic registry container,以及 `StaticToolProvider` / `install_static_provider` 安装合约。dynamic tool provider / decorator contract 已通过 `agent-tools` 提供兼容 re-export,原 `runtime-ports` 路径保持可用;core 旧路径继续 re-export,并只保留 `BitFunError` 映射、路径 containment helper`ToolUseContext` 到 facts 的只读投影
- 已迁移到 `bitfun-agent-tools`:`ToolResult`、`ValidationResult`、`InputValidator`、dynamic tool metadata、tool render options、runtime restriction DTO、path resolution DTO、`ToolContextFacts` / `ToolWorkspaceKind` 轻量上下文事实、`PortableToolContextProvider` 只读 facts provider、不依赖 core service 的 `ToolRegistry<T>` / `ToolRegistryItem` generic registry container`StaticToolProvider` / `install_static_provider` 安装合约,以及 `GetToolSpec` load observation 到 collapsed 工具名集合的纯收集 helper。dynamic tool provider / decorator contract 已通过 `agent-tools` 提供兼容 re-export,原 `runtime-ports` 路径保持可用;core 旧路径继续 re-export,并只保留 `BitFunError` 映射、路径 containment helper`ToolUseContext` 到 facts 的只读投影和 runtime unlock state
- `bitfun-core::agentic::tools` 现在保留 core-owned product provider groups、snapshot decorator 组装、旧构造函数、`dyn Tool` 到 generic registry 的适配、`ToolUseContext` runtime handle / service owner,以及最新主干新增的 runtime manifest assembly / context filtering / `GetToolSpec` 执行;dynamic metadata map、tool map、dynamic descriptor assembly、static provider 安装合约、portable context facts、纯 manifest/exposure 契约和 GetToolSpec presentation/schema 纯 helper 由 `bitfun-agent-tools` 拥有。
- 已新增 `bitfun-tool-packs` feature scaffold,默认 feature 为空,`product-full` 只聚合 feature;当前只提供 `ToolPackFeatureGroup` / `all_feature_groups` / `enabled_feature_groups` 元数据,不注册或迁移任何工具实现。
- 已通过 boundary check 锁定 `agent-tools` / `tool-packs` 暂不拥有 product tool runtime assembly、`GetToolSpecTool` 执行或 collapsed-tool unlock state;`tool-packs` 也不得拥有 manifest/exposure 契约。`agent-tools` 只允许拥有纯 manifest/exposure helper、GetToolSpec presentation/schema helper 和不依赖具体工具的 provider 安装合约,core product tool runtime 继续负责产品 registry snapshot、context-aware discovery、unlock state 和执行路径。
Expand All @@ -1092,6 +1095,13 @@ pub fn create_tool_registry() -> ToolRegistry {
provider group 顺序装配。该切片不移动 concrete tool implementation、`ToolUseContext`、
runtime manifest assembly 或 `GetToolSpec` 执行;provider id、工具顺序与 manifest 快照由
`bitfun-agent-tools` contract test、core registry snapshot 和 boundary check 共同保护。
- H1 follow-up(2026-05-19):下一步先补迁移前 baseline,而不是直接移动 runtime owner。
新增保护应覆盖完整 collapsed 工具清单、`ToolExecutionContext` 到 core-owned
`ToolUseContext` 的运行时状态传递,以及 `ToolContextFacts` / `PortableToolContextProvider`
不携带 `unlocked_collapsed_tools`、custom data、cancellation token 或 workspace services 的边界;
core `resolve_tool_manifest` 还要保留当前显式允许 `GetToolSpec` 时的 runtime insertion 快照。
这仍不声明 `ToolUseContext`、runtime manifest assembly、`GetToolSpecTool` 执行或 concrete
tools 已经外移。

**验证:**

Expand Down Expand Up @@ -1821,8 +1831,9 @@ git diff -- package.json scripts/dev.cjs scripts/desktop-tauri-build.mjs scripts
15. 已完成:agent tools + `tool-packs` owner 化低风险闭环;tool contract / DTO、runtime restriction、path resolution、portable context facts/provider、generic registry / static provider installation / dynamic provider container 已归属 `bitfun-agent-tools`,`tool-packs` 只提供计划内 feature-group scaffold,core 保留 core-owned product provider groups、snapshot decorator、`ToolUseContext` 和 concrete tool implementation,后续外移需单独 service port/provider 设计。
16. 已完成:关键语义回归 baseline,不移动 runtime owner。覆盖 MCP config failure / catalog invalidation / 既有 list-changed helper / dynamic manifest、tool manifest / `GetToolSpec`、product-domains adapter equivalence、remote workspace search fallback 的 focused tests 或 snapshots。
17. 已完成:remote-connect runtime 当前批次收口。已基于当前 port baseline 记录 remote command/response、remote model catalog、poll response、model catalog delta、session restore、active turn、cancel、image context、tracker event、queue/event fanout 的输入输出和验证命令;tracker state / registry lifecycle、legacy image context fallback / preference、restore target decision、cancel decision 与 remote file transfer size/chunk/name policy 已迁入 `bitfun-services-integrations`。dispatcher / product execution、`ImageContextData` adapter、file IO/path resolution、terminal pre-warm 与 workspace/session restore 执行显式保留在 core-owned runtime;后续只有在另起 port/provider 设计且 focused regression 继续通过时才允许继续移动这些 runtime owner,不能把 generic attachment guard 当作已接入多模态行为。
18. 当前阶段:`product-domains` runtime port/facade closure。已迁入 MiniApp storage-backed runtime-state facade、built-in seed plan / marker wire helper 与 function-agent Git/AI port-backed runtime facade,并补充 focused contract tests;core 只对 MiniApp deps/restart/recompile/sync/rollback 的状态持久化委托 facade,仍保留 `PathManager` 注入、filesystem IO、worker process execution、host dispatch 执行、built-in asset seeding/source-hash lookup、prompt template、JSON extraction 和 error mapping adapter。Git commit-message 与 Startchat work-state 产品路径已通过 core-owned Git/AI adapter 接入 function-agent facade;extracted JSON string 可委托 product-domain parser,但 JSON 提取、日志与错误映射仍在 core。Startchat 接线已用 no-HEAD diff fallback、非 Git 目录空状态和 `analyze_git=false` time-info 保护旧行为,`analyzed_at` 仍由 core 在 AI 分析完成后赋值。
19. 后续独立评估:`bitfun-core default = []`、per-product feature set、依赖版本收敛或构建收益优化;任何收益声明都需要记录 `cargo check -p bitfun-core`、workspace check 和目标 crate check 的前后数据。
18. 已完成:`product-domains` runtime port/facade closure。已迁入 MiniApp storage-backed runtime-state facade、built-in seed plan / marker wire helper 与 function-agent Git/AI port-backed runtime facade,并补充 focused contract tests;core 只对 MiniApp deps/restart/recompile/sync/rollback 的状态持久化委托 facade,仍保留 `PathManager` 注入、filesystem IO、worker process execution、host dispatch 执行、built-in asset seeding/source-hash lookup、prompt template、JSON extraction 和 error mapping adapter。Git commit-message 与 Startchat work-state 产品路径已通过 core-owned Git/AI adapter 接入 function-agent facade;extracted JSON string 可委托 product-domain parser,但 JSON 提取、日志与错误映射仍在 core。Startchat 接线已用 no-HEAD diff fallback、非 Git 目录空状态和 `analyze_git=false` time-info 保护旧行为,`analyzed_at` 仍由 core 在 AI 分析完成后赋值。
19. 当前阶段:H1 tool runtime migration baseline。已开始把纯 helper 从 runtime owner 中剥离:`StaticToolProviderGroup` 和 `GetToolSpec` collapsed-load 纯收集规则可由 `bitfun-agent-tools` 拥有;完整 collapsed 工具清单、runtime context 传递和 portable facts 边界回归仍需继续补齐,再评估单一 owner 外移。不得把 `ToolUseContext`、`GetToolSpecTool` 执行、runtime manifest assembly、snapshot decorator 或 concrete tools 的迁移混成隐式结构调整。
20. 后续独立评估:`bitfun-core default = []`、per-product feature set、依赖版本收敛或构建收益优化;任何收益声明都需要记录 `cargo check -p bitfun-core`、workspace check 和目标 crate check 的前后数据。

冗余清理 PR 不进入上述主线序号。只有在满足 `0A.6` 的绝对等价要求时,才可以插入到相邻里程碑之间,并且不得与主线拆分 PR 混合。

Expand Down
22 changes: 22 additions & 0 deletions scripts/check-core-boundaries.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1161,6 +1161,14 @@ const requiredContentRules = [
regex: /\bpub fn build_get_tool_spec_assistant_detail\b/,
message: 'missing pure GetToolSpec assistant detail rendering contract',
},
{
regex: /\bpub struct GetToolSpecLoadObservation\b/,
message: 'missing pure GetToolSpec load observation contract',
},
{
regex: /\bpub fn collect_loaded_collapsed_tool_names\b/,
message: 'missing pure collapsed-tool load collection contract',
},
{
regex: /\bpub fn sort_tool_manifest_definitions\b/,
message: 'missing prompt-visible manifest ordering helper',
Expand Down Expand Up @@ -1215,6 +1223,10 @@ const requiredContentRules = [
regex: /\bget_collapsed_tool_names\b/,
message: 'missing collapsed-tool catalog owner',
},
{
regex: /\bregistry_preserves_collapsed_tool_manifest_for_owner_migration\b/,
message: 'missing collapsed-tool manifest migration baseline',
},
{
regex: /\bToolExposure::Collapsed\b/,
message: 'missing collapsed exposure lookup',
Expand Down Expand Up @@ -1326,6 +1338,10 @@ const requiredContentRules = [
regex: /\bbuild_collapsed_tool_stub_definition\b/,
message: 'missing collapsed-tool prompt stub contract use',
},
{
regex: /\bmanifest_preserves_explicit_get_tool_spec_runtime_contract\b/,
message: 'missing core GetToolSpec manifest insertion regression',
},
],
},
{
Expand Down Expand Up @@ -1391,6 +1407,10 @@ const requiredContentRules = [
regex: /\bunlocked_collapsed_tools\b/,
message: 'missing collapsed-tool unlock state propagation',
},
{
regex: /\bpipeline_preserves_core_owned_tool_context_without_portable_runtime_leak\b/,
message: 'missing ToolUseContext runtime boundary regression',
},
{
regex: /\bGetToolSpec\b/,
message: 'missing GetToolSpec gating contract',
Expand Down Expand Up @@ -2991,6 +3011,8 @@ function runManifestParserSelfTest() {
'get_tool_spec_input_schema',
'validate_get_tool_spec_input',
'build_get_tool_spec_assistant_detail',
'GetToolSpecLoadObservation',
'collect_loaded_collapsed_tool_names',
'sort_tool_manifest_definitions',
],
},
Expand Down
34 changes: 33 additions & 1 deletion src/crates/agent-tools/src/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use bitfun_core_types::ToolImageAttachment;
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::BTreeSet;
use std::collections::{BTreeSet, HashSet};
use std::fmt;
use std::path::{Path, PathBuf};
use std::sync::Arc;
Expand Down Expand Up @@ -259,6 +259,38 @@ pub fn build_get_tool_spec_duplicate_load_hint(tool_name: &str) -> String {
)
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct GetToolSpecLoadObservation<'a> {
pub tool_name: &'a str,
pub loaded_tool_name: Option<&'a str>,
pub is_error: bool,
}

pub fn collect_loaded_collapsed_tool_names(
observations: &[GetToolSpecLoadObservation<'_>],
collapsed_tool_names: &[String],
get_tool_spec_tool_name: &str,
) -> Vec<String> {
let collapsed_set: HashSet<&str> = collapsed_tool_names.iter().map(String::as_str).collect();
let mut loaded = BTreeSet::new();

for observation in observations {
if observation.is_error || observation.tool_name != get_tool_spec_tool_name {
continue;
}

let Some(tool_name) = observation.loaded_tool_name else {
continue;
};

if collapsed_set.contains(tool_name) {
loaded.insert(tool_name.to_string());
}
}

loaded.into_iter().collect()
}

pub fn build_get_tool_spec_assistant_detail(description: &str, input_schema: &Value) -> String {
format!(
"<description>\n{}\n</description>\n<input_schema>\n{}\n</input_schema>",
Expand Down
14 changes: 7 additions & 7 deletions src/crates/agent-tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ pub use bitfun_runtime_ports::{
DynamicToolDescriptor, DynamicToolProvider, PortError, PortErrorKind, PortResult, ToolDecorator,
};
pub use framework::{
DynamicMcpToolInfo, DynamicToolInfo, GET_TOOL_SPEC_TOOL_NAME, PortableToolContextProvider,
StaticToolProvider, StaticToolProviderGroup, ToolContextFacts, ToolExposure,
ToolManifestDefinition, ToolManifestPolicyResolution, ToolManifestPolicyTool, ToolPathBackend,
ToolPathOperation, ToolPathPolicy, ToolPathResolution, ToolRef, ToolRegistry, ToolRegistryItem,
ToolRenderOptions, ToolRestrictionError, ToolResult, ToolRuntimeRestrictions,
DynamicMcpToolInfo, DynamicToolInfo, GET_TOOL_SPEC_TOOL_NAME, GetToolSpecLoadObservation,
PortableToolContextProvider, StaticToolProvider, StaticToolProviderGroup, ToolContextFacts,
ToolExposure, ToolManifestDefinition, ToolManifestPolicyResolution, ToolManifestPolicyTool,
ToolPathBackend, ToolPathOperation, ToolPathPolicy, ToolPathResolution, ToolRef, ToolRegistry,
ToolRegistryItem, ToolRenderOptions, ToolRestrictionError, ToolResult, ToolRuntimeRestrictions,
ToolWorkspaceKind, ValidationResult, build_collapsed_tool_stub_definition,
build_get_tool_spec_assistant_detail, build_get_tool_spec_collapsed_tool_entry,
build_get_tool_spec_description, build_get_tool_spec_duplicate_load_hint,
get_tool_spec_input_schema, resolve_tool_manifest_policy, sort_tool_manifest_definitions,
tool_manifest_sort_rank, validate_get_tool_spec_input,
collect_loaded_collapsed_tool_names, get_tool_spec_input_schema, resolve_tool_manifest_policy,
sort_tool_manifest_definitions, tool_manifest_sort_rank, validate_get_tool_spec_input,
};
pub use input_validator::InputValidator;
53 changes: 47 additions & 6 deletions src/crates/agent-tools/tests/tool_contracts.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use bitfun_agent_tools::{
DynamicMcpToolInfo, DynamicToolInfo, GET_TOOL_SPEC_TOOL_NAME, InputValidator, ToolContextFacts,
ToolExposure, ToolImageAttachment, ToolManifestDefinition, ToolManifestPolicyTool,
ToolPathBackend, ToolPathResolution, ToolRenderOptions, ToolResult, ToolRuntimeRestrictions,
ToolWorkspaceKind, ValidationResult, build_collapsed_tool_stub_definition,
build_get_tool_spec_assistant_detail, build_get_tool_spec_collapsed_tool_entry,
build_get_tool_spec_description, build_get_tool_spec_duplicate_load_hint,
DynamicMcpToolInfo, DynamicToolInfo, GET_TOOL_SPEC_TOOL_NAME, GetToolSpecLoadObservation,
InputValidator, ToolContextFacts, ToolExposure, ToolImageAttachment, ToolManifestDefinition,
ToolManifestPolicyTool, ToolPathBackend, ToolPathResolution, ToolRenderOptions, ToolResult,
ToolRuntimeRestrictions, ToolWorkspaceKind, ValidationResult,
build_collapsed_tool_stub_definition, build_get_tool_spec_assistant_detail,
build_get_tool_spec_collapsed_tool_entry, build_get_tool_spec_description,
build_get_tool_spec_duplicate_load_hint, collect_loaded_collapsed_tool_names,
get_tool_spec_input_schema, resolve_tool_manifest_policy, sort_tool_manifest_definitions,
validate_get_tool_spec_input,
};
Expand Down Expand Up @@ -419,6 +420,46 @@ fn tool_manifest_policy_preserves_explicit_get_tool_spec_duplicate_runtime_contr
assert_eq!(policy.collapsed_tool_names, vec!["WebFetch"]);
}

#[test]
fn get_tool_spec_load_collector_preserves_collapsed_runtime_contract() {
let collapsed_tools = vec!["WebFetch".to_string(), "GetFileDiff".to_string()];
let observations = vec![
GetToolSpecLoadObservation {
tool_name: GET_TOOL_SPEC_TOOL_NAME,
loaded_tool_name: Some("WebFetch"),
is_error: false,
},
GetToolSpecLoadObservation {
tool_name: GET_TOOL_SPEC_TOOL_NAME,
loaded_tool_name: Some("Read"),
is_error: false,
},
GetToolSpecLoadObservation {
tool_name: GET_TOOL_SPEC_TOOL_NAME,
loaded_tool_name: Some("GetFileDiff"),
is_error: true,
},
GetToolSpecLoadObservation {
tool_name: "Read",
loaded_tool_name: Some("WebFetch"),
is_error: false,
},
GetToolSpecLoadObservation {
tool_name: GET_TOOL_SPEC_TOOL_NAME,
loaded_tool_name: Some("WebFetch"),
is_error: false,
},
];

let loaded = collect_loaded_collapsed_tool_names(
&observations,
&collapsed_tools,
GET_TOOL_SPEC_TOOL_NAME,
);

assert_eq!(loaded, vec!["WebFetch".to_string()]);
}

#[test]
fn collapsed_tool_stub_definition_preserves_prompt_visible_guardrail() {
let stub = build_collapsed_tool_stub_definition(
Expand Down
Loading
Loading