From 7b81c4db73f3239e6772c44818236b629556b75e Mon Sep 17 00:00:00 2001 From: Gab Date: Tue, 24 Mar 2026 17:59:49 +1100 Subject: [PATCH] feat: skills and agents --- .../__pycache__/config.cpython-313.pyc | Bin 8395 -> 8430 bytes .../tf_sync/__pycache__/tools.cpython-313.pyc | Bin 7170 -> 7241 bytes packages/tf-sync/src/tf_sync/config.py | 1 + packages/tf-sync/src/tf_sync/tools.py | 6 ++-- packages/tfcode/src/agent/agent.ts | 2 +- packages/tfcode/src/skill/index.ts | 26 +++++++++++++++++- 6 files changed, 31 insertions(+), 4 deletions(-) diff --git a/packages/tf-sync/src/tf_sync/__pycache__/config.cpython-313.pyc b/packages/tf-sync/src/tf_sync/__pycache__/config.cpython-313.pyc index e1a47a6daa55caaea67bc1ea4e0dd6c79bc667ba..5b8500a980f5af75f52523f5fa9967538af8a963 100644 GIT binary patch delta 847 zcmZ9K&ubG=5XbwP-6Y*@+9Z{xk|rr4(j_RV2hl@Qvu!ja#cJ>uwvsm6C2SjZ!({s- zr?!WRh=@2~FBKF7DdM4S{{r!(;JNI5OIojLIEyCK78<7Q;uGl{Q*d9p(5p_)OckrO!u8^f z+xT75qe))mQP*KCwOKxlXErOCl{Z)#-^-tsESG?g#!m1G%X(gLClEhRQI(M3&=}}A zr;NzgxKsAFlpJF-_)*oFj(^mL(j*V##?YYG>}|69Qo` zIw4G;bU)fK-CEl;fd5t(nky!hG1r%8bLjN_I(3z&>~)_k++%PDp?{3o__lvHS)eix z2(uh*#xVlJP@bC6~K$Yf>@Q3G!xR7j delta 884 zcmZvaT}TvB6vy|vv$O85`)Rt`x~>(0i%|9wMY-;p%4)F%R#;J{+n@tFBX`F|BU(ZF zKq8_;AhFO(1U|;}QZE$%vgZMHYn8}3*a+yNjikY+qf6@Q1PUl>F7Q-3#O1^N`|V_9lx zxXf~Px#1QYJ%;$>Ko62UdH)l0&E%1wQ$lAN1qCf(W zr3aw^>{)suaL4soIruf!^igTr2-0$Ng$>faSe4Dwn^-r?(`M}O;1y(z16Kh#McKd@ z%qc(z{#Q|h1DL0o#=d|wBQG~gFXO$QIkCKGZ^uu$1Cv75{8Mx`kx`|s+bfAAJ0hnRwzQHpRx}Mm zD_XiJx6_>uxj3HV8<;O@vv8*sUZ(GD8PAefe`a?l?=w}7#-O$KiM$+!e5dV5P6K%G z^4anhs8-;FfTLW~i&pLJ$UBjh(K}xvBb8*!bT8EtQrOT_;j1= fCQC@mGNw;9lg{7~W@MY8^@RaQebAY_N;(1nFy>R; delta 271 zcmX?U(PY8wLeSt&+!xxdsJNT^`r8j@!k7r?Yo*W{g!{{=(QN)1JY4Ro!JJv{`s%Xlf4KeUZe#g#6W}qhzI}?fgnNyNN92txq#SFliy3ov4w+}5tD@_wOHeU z% SyncedTool: """ Parse Agent from SDK into SyncedTool. + Coder agents (mode='coder') are CODER_AGENT type, not skills. + Args: agent: Agent from TF SDK @@ -125,8 +127,8 @@ def parse_agent(agent) -> 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, + tool_type=ToolType.CODER_AGENT, + is_agent_skill=False, auth_via="tf_agent", ) diff --git a/packages/tfcode/src/agent/agent.ts b/packages/tfcode/src/agent/agent.ts index d434595f7..8e7c3c303 100644 --- a/packages/tfcode/src/agent/agent.ts +++ b/packages/tfcode/src/agent/agent.ts @@ -263,7 +263,7 @@ export namespace Agent { if (!data.success || !data.tools) return [] return data.tools - .filter((t: any) => t.tool_type === "agent_skill") + .filter((t: any) => t.tool_type === "coder_agent") .map((t: any): Info => ({ name: t.name, description: t.description, diff --git a/packages/tfcode/src/skill/index.ts b/packages/tfcode/src/skill/index.ts index 43a22219e..34b9d555c 100644 --- a/packages/tfcode/src/skill/index.ts +++ b/packages/tfcode/src/skill/index.ts @@ -201,7 +201,31 @@ export namespace Skill { const all = Effect.fn("Skill.all")(function* () { const cache = yield* ensure() - return Object.values(cache.skills) + const skills = Object.values(cache.skills) + + // Add TF agent skills from synced tools (only agent_skill type, not coder_agent) + const toolsPath = path.join(Global.Path.data, ".tfcode", "tools.json") + try { + const content = yield* Effect.promise(() => Bun.file(toolsPath).text()) + const data = JSON.parse(content) as { success: boolean; tools: Array<{ tool_type: string; name: string; description?: string; id: string }> } + if (data.success && data.tools) { + for (const tool of data.tools) { + // Only include agent_skill (from is_agent_skill=True), not coder_agent + if (tool.tool_type === "agent_skill") { + skills.push({ + name: tool.name, + description: tool.description || "ToothFairyAI Agent Skill", + location: `tf://${tool.id}`, + content: "", + }) + } + } + } + } catch { + // Ignore errors loading TF tools + } + + return skills }) const dirs = Effect.fn("Skill.dirs")(function* () {