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
6 changes: 3 additions & 3 deletions docs/architecture/core-decomposition.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,9 @@ owner 边界,否则不要把一个 feature group 继续拆成更小的 crate
处理前,必须保留 `report.md` / `citations.md` / `display_map.json` 的 deterministic post-processing 行为;
在此之前该 hook 仍属于 `bitfun-core` agent runtime assembly。
- 最新主干新增 on-demand tool spec discovery。`ToolExposure`、`GetToolSpec` 名称、
collapsed stub、manifest ordering、GetToolSpec prompt / schema / assistant-detail
rendering 等纯契约可由 `bitfun-agent-tools` 拥有;但
`manifest_resolver`、产品 registry snapshot、collapsed-tool catalog、context-aware
collapsed stub、manifest ordering、generic collapsed exposure query、GetToolSpec
prompt / schema / assistant-detail rendering 等纯契约可由 `bitfun-agent-tools`
拥有;但 `manifest_resolver`、产品 registry snapshot、product collapsed-tool catalog、context-aware
tool schema/description、`GetToolSpec` 执行和 `ToolUseContext.unlocked_collapsed_tools`
暂时仍属于 `bitfun-core` product tool runtime。继续迁移前必须证明 prompt-visible
manifest、expanded/collapsed exposure、unlock state 与 desktop/MCP/ACP tool catalog 等价。
Expand Down
28 changes: 17 additions & 11 deletions docs/plans/core-decomposition-plan.md

Large diffs are not rendered by default.

60 changes: 55 additions & 5 deletions scripts/check-core-boundaries.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1141,14 +1141,38 @@ const requiredContentRules = [
regex: /\bpub fn resolve_tool_manifest_policy\b/,
message: 'missing pure tool manifest policy resolver',
},
{
regex: /\bfn default_exposure\b/,
message: 'missing generic tool exposure contract',
},
{
regex: /\bpub fn build_tool_manifest_policy_tools\b/,
message: 'missing registry snapshot to manifest policy input helper',
},
{
regex: /\bpub fn build_collapsed_tool_stub_definition\b/,
message: 'missing collapsed-tool prompt stub contract',
},
{
regex: /\bpub enum PromptVisibleToolManifestItem\b/,
message: 'missing prompt-visible manifest item contract',
},
{
regex: /\bpub fn build_prompt_visible_tool_manifest_definitions\b/,
message: 'missing prompt-visible manifest definition builder',
},
{
regex: /\bpub fn build_get_tool_spec_description\b/,
message: 'missing pure GetToolSpec prompt description contract',
},
{
regex: /\bpub struct GetToolSpecCollapsedToolSummary\b/,
message: 'missing pure GetToolSpec collapsed catalog summary',
},
{
regex: /\bpub fn build_get_tool_spec_catalog_description\b/,
message: 'missing pure GetToolSpec catalog description builder',
},
{
regex: /\bpub fn get_tool_spec_input_schema\b/,
message: 'missing pure GetToolSpec input schema contract',
Expand Down Expand Up @@ -1177,6 +1201,14 @@ const requiredContentRules = [
regex: /\bpub struct StaticToolProviderGroup\b/,
message: 'missing generic static provider group container',
},
{
regex: /\bpub fn is_tool_collapsed\b/,
message: 'missing generic collapsed-tool registry query',
},
{
regex: /\bpub fn get_collapsed_tool_names\b/,
message: 'missing generic collapsed-tool registry catalog query',
},
],
},
{
Expand Down Expand Up @@ -1228,8 +1260,8 @@ const requiredContentRules = [
message: 'missing collapsed-tool manifest migration baseline',
},
{
regex: /\bToolExposure::Collapsed\b/,
message: 'missing collapsed exposure lookup',
regex: /\binner\.is_tool_collapsed\b/,
message: 'missing collapsed exposure lookup delegation',
},
],
},
Expand Down Expand Up @@ -1330,13 +1362,17 @@ const requiredContentRules = [
regex: /\bresolve_tool_manifest_policy\b/,
message: 'missing agent-tools manifest policy contract use',
},
{
regex: /\bbuild_tool_manifest_policy_tools\b/,
message: 'missing agent-tools manifest policy input builder delegation',
},
{
regex: /\bcollapsed_tool_names\b/,
message: 'missing collapsed-tool name tracking',
},
{
regex: /\bbuild_collapsed_tool_stub_definition\b/,
message: 'missing collapsed-tool prompt stub contract use',
regex: /\bbuild_prompt_visible_tool_manifest_definitions\b/,
message: 'missing agent-tools prompt-visible manifest builder delegation',
},
{
regex: /\bmanifest_preserves_explicit_get_tool_spec_runtime_contract\b/,
Expand Down Expand Up @@ -1365,6 +1401,10 @@ const requiredContentRules = [
regex: /\bbuild_get_tool_spec_assistant_detail\b/,
message: 'missing agent-tools GetToolSpec assistant detail helper delegation',
},
{
regex: /\bbuild_get_tool_spec_catalog_description\b/,
message: 'missing agent-tools GetToolSpec catalog description helper delegation',
},
{
regex: /\bvalidate_get_tool_spec_input\b/,
message: 'missing agent-tools GetToolSpec validation helper delegation',
Expand Down Expand Up @@ -3006,14 +3046,22 @@ function runManifestParserSelfTest() {
'ToolExposure',
'ToolManifestPolicyTool',
'resolve_tool_manifest_policy',
'default_exposure',
'build_tool_manifest_policy_tools',
'build_collapsed_tool_stub_definition',
'PromptVisibleToolManifestItem',
'build_prompt_visible_tool_manifest_definitions',
'build_get_tool_spec_description',
'GetToolSpecCollapsedToolSummary',
'build_get_tool_spec_catalog_description',
'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',
'is_tool_collapsed',
'get_collapsed_tool_names',
],
},
{
Expand Down Expand Up @@ -3136,7 +3184,8 @@ function runManifestParserSelfTest() {
'resolve_tool_manifest',
'GET_TOOL_SPEC_TOOL_NAME',
'resolve_tool_manifest_policy',
'build_collapsed_tool_stub_definition',
'build_tool_manifest_policy_tools',
'build_prompt_visible_tool_manifest_definitions',
'collapsed_tool_names',
],
},
Expand All @@ -3147,6 +3196,7 @@ function runManifestParserSelfTest() {
'unlocked_collapsed_tools',
'already_loaded',
'build_get_tool_spec_assistant_detail',
'build_get_tool_spec_catalog_description',
'validate_get_tool_spec_input',
],
},
Expand Down
86 changes: 86 additions & 0 deletions src/crates/agent-tools/src/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ impl ToolManifestDefinition {
}
}

#[derive(Debug, Clone, PartialEq)]
pub enum PromptVisibleToolManifestItem {
Expanded(ToolManifestDefinition),
Collapsed {
name: String,
short_description: String,
},
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ToolManifestPolicyTool {
pub name: String,
Expand Down Expand Up @@ -151,6 +160,23 @@ pub fn resolve_tool_manifest_policy(
}
}

pub fn build_tool_manifest_policy_tools<Tool: ToolRegistryItem + ?Sized>(
tool_snapshot: &[ToolRef<Tool>],
available_tool_names: &HashSet<String>,
) -> Vec<ToolManifestPolicyTool> {
tool_snapshot
.iter()
.map(|tool| {
let name = tool.name().to_string();
ToolManifestPolicyTool {
available: available_tool_names.contains(&name),
default_exposure: tool.default_exposure(),
name,
}
})
.collect()
}

pub fn build_collapsed_tool_stub_definition(
tool_name: &str,
short_description: &str,
Expand Down Expand Up @@ -185,6 +211,30 @@ pub fn build_get_tool_spec_collapsed_tool_entry(
format!("- {}: {}", tool_name, short_description)
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GetToolSpecCollapsedToolSummary {
pub name: String,
pub short_description: String,
}

pub fn build_get_tool_spec_catalog_description(
collapsed_tools: &[GetToolSpecCollapsedToolSummary],
) -> String {
let collapsed_tools_list = if collapsed_tools.is_empty() {
"No additional tools are available.".to_string()
} else {
collapsed_tools
.iter()
.map(|tool| {
build_get_tool_spec_collapsed_tool_entry(&tool.name, &tool.short_description)
})
.collect::<Vec<_>>()
.join("\n")
};

build_get_tool_spec_description(&collapsed_tools_list)
}

pub fn build_get_tool_spec_description(collapsed_tools_list: &str) -> String {
format!(
r#"Read usage instructions for additional tools.
Expand Down Expand Up @@ -332,6 +382,23 @@ pub fn sort_tool_manifest_definitions(tool_definitions: &mut [ToolManifestDefini
tool_definitions.sort_by_key(|tool| tool_manifest_sort_rank(&tool.name));
}

pub fn build_prompt_visible_tool_manifest_definitions(
items: &[PromptVisibleToolManifestItem],
) -> Vec<ToolManifestDefinition> {
let mut definitions = items
.iter()
.map(|item| match item {
PromptVisibleToolManifestItem::Expanded(definition) => definition.clone(),
PromptVisibleToolManifestItem::Collapsed {
name,
short_description,
} => build_collapsed_tool_stub_definition(name, short_description),
})
.collect::<Vec<_>>();
sort_tool_manifest_definitions(&mut definitions);
definitions
}

#[async_trait]
pub trait ToolRegistryItem: Send + Sync {
fn name(&self) -> &str;
Expand All @@ -340,6 +407,10 @@ pub trait ToolRegistryItem: Send + Sync {

fn input_schema(&self) -> Value;

fn default_exposure(&self) -> ToolExposure {
ToolExposure::Expanded
}

async fn input_schema_for_model(&self) -> Value {
self.input_schema()
}
Expand Down Expand Up @@ -508,6 +579,21 @@ impl<Tool: ToolRegistryItem + ?Sized> ToolRegistry<Tool> {
.map(|metadata| metadata.info.clone())
}

pub fn is_tool_collapsed(&self, name: &str) -> bool {
self.tools
.get(name)
.is_some_and(|tool| tool.default_exposure() == ToolExposure::Collapsed)
}

pub fn get_collapsed_tool_names(&self) -> Vec<String> {
self.tools
.iter()
.filter_map(|(name, tool)| {
(tool.default_exposure() == ToolExposure::Collapsed).then(|| name.clone())
})
.collect()
}

pub fn get_tool_names(&self) -> Vec<String> {
self.tools.keys().cloned().collect()
}
Expand Down
21 changes: 12 additions & 9 deletions src/crates/agent-tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,18 @@ pub use bitfun_runtime_ports::{
DynamicToolDescriptor, DynamicToolProvider, PortError, PortErrorKind, PortResult, ToolDecorator,
};
pub use framework::{
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,
DynamicMcpToolInfo, DynamicToolInfo, GET_TOOL_SPEC_TOOL_NAME, GetToolSpecCollapsedToolSummary,
GetToolSpecLoadObservation, PortableToolContextProvider, PromptVisibleToolManifestItem,
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,
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,
build_get_tool_spec_assistant_detail, build_get_tool_spec_catalog_description,
build_get_tool_spec_collapsed_tool_entry, build_get_tool_spec_description,
build_get_tool_spec_duplicate_load_hint, build_prompt_visible_tool_manifest_definitions,
build_tool_manifest_policy_tools, 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;
Loading
Loading