feat: initialize tfcode project structure

- Add README.md as living documentation
- Add tfcode.json schema and config template
- Add FORK_MANAGEMENT.md with mirror-based fork strategy
- Add scripts/rebrand.sh for reapplying branding after upstream merges
- Add packages/tf-sync Python module using official ToothFairyAI SDK
- Add packages/tf-mcp-bridge TypeScript module (stub)
- Multi-region support (AU, EU, US)
- Tool sync: MCP servers, Agent Skills, Database Scripts, API Functions
This commit is contained in:
Gab
2026-03-24 13:02:06 +11:00
parent 7bb69038ec
commit abdfa7330e
14 changed files with 1627 additions and 0 deletions

View File

@@ -0,0 +1,185 @@
"""
Tool sync module for tfcode.
Syncs MCP servers, Agent Skills, Database Scripts, and API Functions from ToothFairyAI workspace.
Uses the official ToothFairyAI Python SDK.
"""
from typing import Any, Optional
from pydantic import BaseModel
from toothfairyai.types import AgentFunction
from tf_sync.config import TFConfig, ToolType, FunctionRequestType
class SyncedTool(BaseModel):
"""A tool synced from ToothFairyAI workspace."""
id: str
name: str
description: Optional[str] = None
tool_type: ToolType
is_mcp_server: bool = False
is_agent_skill: bool = False
is_database_script: bool = False
request_type: Optional[FunctionRequestType] = None
url: Optional[str] = None
tools: list[str] = []
auth_via: str = "tf_proxy"
class ToolSyncResult(BaseModel):
"""Result of tool sync operation."""
success: bool
tools: list[SyncedTool] = []
by_type: dict[str, int] = {}
error: Optional[str] = None
def classify_tool(tool: AgentFunction) -> ToolType:
"""
Classify a tool based on its flags and fields.
Args:
tool: AgentFunction from TF SDK
Returns:
ToolType enum value
"""
if tool.is_mcp_server:
return ToolType.MCP_SERVER
if tool.is_agent_skill:
return ToolType.AGENT_SKILL
if tool.is_database_script:
return ToolType.DATABASE_SCRIPT
if tool.request_type:
return ToolType.API_FUNCTION
return ToolType.API_FUNCTION
def parse_tool(tool: AgentFunction) -> SyncedTool:
"""
Parse AgentFunction from SDK into SyncedTool.
Args:
tool: AgentFunction from TF SDK
Returns:
SyncedTool instance
"""
tool_type = classify_tool(tool)
request_type_enum = None
if tool.request_type:
try:
request_type_enum = FunctionRequestType(tool.request_type)
except ValueError:
pass
auth_via = "user_provided" if tool_type == ToolType.API_FUNCTION else "tf_proxy"
return SyncedTool(
id=tool.id,
name=tool.name,
description=tool.description,
tool_type=tool_type,
is_mcp_server=tool.is_mcp_server or False,
is_agent_skill=tool.is_agent_skill or False,
is_database_script=tool.is_database_script or False,
request_type=request_type_enum,
url=tool.url,
tools=[],
auth_via=auth_via,
)
def sync_tools(config: TFConfig) -> ToolSyncResult:
"""
Sync all tools from ToothFairyAI workspace using SDK.
Args:
config: TFConfig instance
Returns:
ToolSyncResult with synced tools
"""
try:
client = config.get_client()
result = client.agent_functions.list()
tools = [parse_tool(f) for f in result.items]
by_type = {}
for tool in tools:
type_name = tool.tool_type.value
by_type[type_name] = by_type.get(type_name, 0) + 1
return ToolSyncResult(
success=True,
tools=tools,
by_type=by_type,
)
except Exception as e:
return ToolSyncResult(
success=False,
error=f"Sync failed: {str(e)}",
)
def sync_tools_by_type(
config: TFConfig,
tool_types: Optional[list[ToolType]] = None,
) -> ToolSyncResult:
"""
Sync tools of specific types from ToothFairyAI workspace.
Args:
config: TFConfig instance
tool_types: List of ToolType to sync (None = all)
Returns:
ToolSyncResult with filtered tools
"""
result = sync_tools(config)
if not result.success or not tool_types:
return result
filtered = [t for t in result.tools if t.tool_type in tool_types]
by_type = {}
for tool in filtered:
type_name = tool.tool_type.value
by_type[type_name] = by_type.get(type_name, 0) + 1
return ToolSyncResult(
success=True,
tools=filtered,
by_type=by_type,
)
def sync_mcp_servers_only(config: TFConfig) -> ToolSyncResult:
"""Sync only MCP servers (isMCPServer=true)."""
return sync_tools_by_type(config, [ToolType.MCP_SERVER])
def sync_agent_skills_only(config: TFConfig) -> ToolSyncResult:
"""Sync only Agent Skills (isAgentSkill=true)."""
return sync_tools_by_type(config, [ToolType.AGENT_SKILL])
def sync_database_scripts_only(config: TFConfig) -> ToolSyncResult:
"""Sync only Database Scripts (isDatabaseScript=true)."""
return sync_tools_by_type(config, [ToolType.DATABASE_SCRIPT])
def sync_api_functions_only(config: TFConfig) -> ToolSyncResult:
"""Sync only API Functions (has requestType)."""
return sync_tools_by_type(config, [ToolType.API_FUNCTION])