mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-03-29 21:33:54 +00:00
feat: tf code
This commit is contained in:
parent
1539afc803
commit
1c0c0e6a50
Binary file not shown.
@ -24,8 +24,13 @@ class SyncedTool(BaseModel):
|
|||||||
description: Optional[str] = None
|
description: Optional[str] = None
|
||||||
tool_type: ToolType
|
tool_type: ToolType
|
||||||
|
|
||||||
|
is_mcp_server: bool = False
|
||||||
|
is_agent_skill: bool = False
|
||||||
|
is_database_script: bool = False
|
||||||
|
|
||||||
request_type: Optional[FunctionRequestType] = None
|
request_type: Optional[FunctionRequestType] = None
|
||||||
url: Optional[str] = None
|
url: Optional[str] = None
|
||||||
|
tools: list[str] = []
|
||||||
|
|
||||||
authorisation_type: Optional[str] = None
|
authorisation_type: Optional[str] = None
|
||||||
|
|
||||||
@ -96,10 +101,34 @@ def parse_function(func: AgentFunction) -> SyncedTool:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_agent(agent) -> SyncedTool:
|
||||||
|
"""
|
||||||
|
Parse Agent from SDK into SyncedTool.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
agent: Agent from TF SDK
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
SyncedTool instance
|
||||||
|
"""
|
||||||
|
return SyncedTool(
|
||||||
|
id=agent.id,
|
||||||
|
name=agent.label or f"agent_{agent.id[:8]}",
|
||||||
|
description=agent.description,
|
||||||
|
tool_type=ToolType.AGENT_SKILL,
|
||||||
|
is_agent_skill=True,
|
||||||
|
auth_via="tf_agent",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def sync_tools(config: TFConfig) -> ToolSyncResult:
|
def sync_tools(config: TFConfig) -> ToolSyncResult:
|
||||||
"""
|
"""
|
||||||
Sync all tools from ToothFairyAI workspace using SDK.
|
Sync all tools from ToothFairyAI workspace using SDK.
|
||||||
|
|
||||||
|
Includes:
|
||||||
|
- Agent Functions (API Functions)
|
||||||
|
- Coder Agents (agents with mode='coder')
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
config: TFConfig instance
|
config: TFConfig instance
|
||||||
|
|
||||||
@ -108,9 +137,19 @@ def sync_tools(config: TFConfig) -> ToolSyncResult:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
client = config.get_client()
|
client = config.get_client()
|
||||||
result = client.agent_functions.list()
|
|
||||||
|
|
||||||
tools = [parse_function(f) for f in result.items]
|
# Sync agent functions
|
||||||
|
func_result = client.agent_functions.list()
|
||||||
|
tools = [parse_function(f) for f in func_result.items]
|
||||||
|
|
||||||
|
# Sync coder agents
|
||||||
|
try:
|
||||||
|
agents_result = client.agents.list()
|
||||||
|
for agent in agents_result.items:
|
||||||
|
if getattr(agent, 'mode', None) == 'coder':
|
||||||
|
tools.append(parse_agent(agent))
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
by_type = {}
|
by_type = {}
|
||||||
for tool in tools:
|
for tool in tools:
|
||||||
|
|||||||
@ -255,10 +255,50 @@ export namespace Agent {
|
|||||||
return state().then((x) => x[agent])
|
return state().then((x) => x[agent])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function loadTFCoderAgents(): Promise<Info[]> {
|
||||||
|
const toolsPath = path.join(Global.Path.data, ".tfcode", "tools.json")
|
||||||
|
console.log("[TF Agents] Loading from:", toolsPath)
|
||||||
|
try {
|
||||||
|
const content = await Bun.file(toolsPath).text()
|
||||||
|
const data = JSON.parse(content)
|
||||||
|
console.log("[TF Agents] File loaded, success:", data.success, "tools:", data.tools?.length)
|
||||||
|
if (!data.success || !data.tools) {
|
||||||
|
console.log("[TF Agents] No tools data, returning []")
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const tfAgents = data.tools
|
||||||
|
.filter((t: any) => t.tool_type === "agent_skill")
|
||||||
|
|
||||||
|
console.log("[TF Agents] Found agent_skill items:", tfAgents.length)
|
||||||
|
console.log("[TF Agents] Names:", tfAgents.map((t: any) => t.name))
|
||||||
|
|
||||||
|
return tfAgents.map((t: any): Info => ({
|
||||||
|
name: t.name,
|
||||||
|
description: t.description,
|
||||||
|
mode: "subagent" as const,
|
||||||
|
permission: Permission.fromConfig({ "*": "allow" }),
|
||||||
|
native: false,
|
||||||
|
options: {
|
||||||
|
tf_agent_id: t.id,
|
||||||
|
tf_auth_via: t.auth_via,
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
} catch (e) {
|
||||||
|
console.log("[TF Agents] Error:", e)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function list() {
|
export async function list() {
|
||||||
const cfg = await Config.get()
|
const cfg = await Config.get()
|
||||||
|
const localAgents = await state()
|
||||||
|
const tfAgents = await loadTFCoderAgents()
|
||||||
|
|
||||||
|
console.log("[TF Agents] list() - local:", Object.keys(localAgents).length, "tf:", tfAgents.length)
|
||||||
|
|
||||||
return pipe(
|
return pipe(
|
||||||
await state(),
|
{ ...localAgents, ...Object.fromEntries(tfAgents.map(a => [a.name, a])) },
|
||||||
values(),
|
values(),
|
||||||
sortBy(
|
sortBy(
|
||||||
[(x) => (cfg.default_agent ? x.name === cfg.default_agent : x.name === "build"), "desc"],
|
[(x) => (cfg.default_agent ? x.name === cfg.default_agent : x.name === "build"), "desc"],
|
||||||
|
|||||||
@ -62,6 +62,8 @@ async function runPythonSync(
|
|||||||
method: string,
|
method: string,
|
||||||
args: Record<string, unknown> = {},
|
args: Record<string, unknown> = {},
|
||||||
): Promise<unknown> {
|
): Promise<unknown> {
|
||||||
|
const credentials = await loadCredentials()
|
||||||
|
|
||||||
const pythonCode = `
|
const pythonCode = `
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
@ -162,6 +164,9 @@ sys.exit(0)
|
|||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
PYTHONPATH: getPythonSyncPath(),
|
PYTHONPATH: getPythonSyncPath(),
|
||||||
|
TF_WORKSPACE_ID: credentials?.workspace_id || "",
|
||||||
|
TF_API_KEY: credentials?.api_key || "",
|
||||||
|
TF_REGION: credentials?.region || "au",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -204,6 +209,23 @@ function getToolsFilePath(): string {
|
|||||||
return path.join(getConfigPath(), TFCODE_TOOLS_FILE)
|
return path.join(getConfigPath(), TFCODE_TOOLS_FILE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCredentialsFilePath(): string {
|
||||||
|
return path.join(getConfigPath(), "credentials.json")
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadCredentials(): Promise<{ workspace_id: string; api_key: string; region: string } | null> {
|
||||||
|
const credFile = getCredentialsFilePath()
|
||||||
|
if (!(await Filesystem.exists(credFile))) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const content = await Bun.file(credFile).text()
|
||||||
|
return JSON.parse(content)
|
||||||
|
} catch {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function loadCachedTools(): Promise<ToolSyncResult | null> {
|
async function loadCachedTools(): Promise<ToolSyncResult | null> {
|
||||||
const toolsFile = getToolsFilePath()
|
const toolsFile = getToolsFilePath()
|
||||||
if (!(await Filesystem.exists(toolsFile))) {
|
if (!(await Filesystem.exists(toolsFile))) {
|
||||||
|
|||||||
@ -44,7 +44,7 @@ export namespace UI {
|
|||||||
const result: string[] = []
|
const result: string[] = []
|
||||||
const reset = "\x1b[0m"
|
const reset = "\x1b[0m"
|
||||||
const left = {
|
const left = {
|
||||||
fg: Bun.color("gray", "ansi") ?? "",
|
fg: "\x1b[38;2;29;184;198m",
|
||||||
shadow: "\x1b[38;5;235m",
|
shadow: "\x1b[38;5;235m",
|
||||||
bg: "\x1b[48;5;235m",
|
bg: "\x1b[48;5;235m",
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user