feat: integration with agents

This commit is contained in:
Gab
2026-03-27 08:42:09 +11:00
parent cf023340a6
commit b9ced47bf8
11 changed files with 1341 additions and 223 deletions

View File

@@ -8,6 +8,7 @@ import { Instance } from "../project/instance"
import { Truncate } from "../tool/truncate"
import { Auth } from "../auth"
import { ProviderTransform } from "../provider/transform"
import os from "os"
import PROMPT_GENERATE from "./generate.txt"
import PROMPT_COMPACTION from "./prompt/compaction.txt"
@@ -41,6 +42,7 @@ export namespace Agent {
.optional(),
variant: z.string().optional(),
prompt: z.string().optional(),
goals: z.string().optional(),
options: z.record(z.string(), z.any()),
steps: z.number().int().positive().optional(),
})
@@ -263,7 +265,8 @@ export namespace Agent {
}
async function loadTFCoderAgents(): Promise<Info[]> {
const toolsPath = path.join(Global.Path.data, ".tfcode", "tools.json")
// tools.json is synced to ~/.tfcode/tools.json by the CLI
const toolsPath = path.join(os.homedir(), ".tfcode", "tools.json")
try {
const content = await Bun.file(toolsPath).text()
const data = JSON.parse(content)
@@ -271,19 +274,33 @@ export namespace Agent {
return data.tools
.filter((t: any) => t.tool_type === "coder_agent")
.map(
(t: any): Info => ({
.map((t: any): Info => {
// Map model for ToothFairyAI providers only
// Only map when llm_provider is None, "toothfairyai", or "tf"
const isTFProvider = !t.llm_provider || t.llm_provider === "toothfairyai" || t.llm_provider === "tf"
const model =
isTFProvider && t.llm_base_model
? { modelID: t.llm_base_model as ModelID, providerID: "toothfairyai" as ProviderID }
: undefined
return {
name: t.name,
description: t.description,
mode: "primary" as const,
permission: Permission.fromConfig({ "*": "allow" }),
native: false,
prompt: t.interpolation_string,
goals: t.goals,
temperature: t.temperature,
model,
options: {
tf_agent_id: t.id,
tf_auth_via: t.auth_via,
tf_max_tokens: t.max_tokens,
},
}),
)
}
})
} catch {
return []
}

View File

@@ -68,10 +68,16 @@ export namespace LLM {
const isOpenaiOauth = provider.id === "openai" && auth?.type === "oauth"
const system: string[] = []
// Build highlighted agent instructions for ToothFairyAI agents
const tfHighlightedInstructions = buildTFAgentInstructions(input.agent)
system.push(
[
// use agent prompt otherwise provider prompt
...(input.agent.prompt ? [input.agent.prompt] : SystemPrompt.provider(input.model)),
// highlighted TF agent instructions (if any)
...(tfHighlightedInstructions ? [tfHighlightedInstructions] : []),
// any custom prompt passed into this call
...input.system,
// any custom prompt from last user message
@@ -168,7 +174,7 @@ export namespace LLM {
const maxOutputTokens =
isOpenaiOauth || provider.id.includes("github-copilot")
? undefined
: ProviderTransform.maxOutputTokens(input.model)
: (input.agent.options?.tf_max_tokens ?? ProviderTransform.maxOutputTokens(input.model))
const tools = await resolveTools(input)
@@ -320,4 +326,63 @@ export namespace LLM {
}
return false
}
/**
* Build highlighted instructions for ToothFairyAI agents.
* When a TF agent is selected, its instructions and goals are highlighted
* as ULTRA IMPORTANT to ensure they are followed with highest priority.
*/
function buildTFAgentInstructions(agent: Agent.Info): string | null {
// Only highlight for ToothFairyAI agents (non-native with tf_agent_id)
const isTFAgent = !agent.native && agent.options?.tf_agent_id
if (!isTFAgent) return null
const parts: string[] = []
// Check if agent has custom prompt (interpolation_string) or goals
const hasPrompt = agent.prompt && agent.prompt.trim().length > 0
const hasGoals = agent.goals && agent.goals.trim().length > 0
if (!hasPrompt && !hasGoals) return null
parts.push("")
parts.push("═══════════════════════════════════════════════════════════════════════════════")
parts.push("⚠️ ULTRA IMPORTANT - AGENT CONFIGURATION ⚠️")
parts.push("═══════════════════════════════════════════════════════════════════════════════")
parts.push("")
parts.push(`You are acting as the agent: "${agent.name}"`)
if (agent.description) {
parts.push(`Description: ${agent.description}`)
}
parts.push("")
parts.push("The following instructions and goals are MANDATORY and MUST be followed")
parts.push("with the HIGHEST PRIORITY. These override any conflicting default behaviors.")
parts.push("═══════════════════════════════════════════════════════════════════════════════")
if (hasPrompt) {
parts.push("")
parts.push("┌─────────────────────────────────────────────────────────────────────────────┐")
parts.push(`│ 🎯 AGENT "${agent.name}" INSTRUCTIONS (CRITICAL - MUST FOLLOW) │`)
parts.push("└─────────────────────────────────────────────────────────────────────────────┘")
parts.push("")
parts.push(agent.prompt!)
}
if (hasGoals) {
parts.push("")
parts.push("┌─────────────────────────────────────────────────────────────────────────────┐")
parts.push(`│ 🎯 AGENT "${agent.name}" GOALS (CRITICAL - MUST ACHIEVE) │`)
parts.push("└─────────────────────────────────────────────────────────────────────────────┘")
parts.push("")
parts.push(agent.goals!)
}
parts.push("")
parts.push("═══════════════════════════════════════════════════════════════════════════════")
parts.push(`⚠️ END OF ULTRA IMPORTANT AGENT "${agent.name}" CONFIGURATION ⚠️`)
parts.push("═══════════════════════════════════════════════════════════════════════════════")
parts.push("")
return parts.join("\n")
}
}