feat: tf code

This commit is contained in:
Gab 2026-03-24 18:27:16 +11:00
parent 2ad192a312
commit 1460f80d1a
6 changed files with 29 additions and 25 deletions

View File

@ -268,20 +268,20 @@ function App() {
if (!terminalTitleEnabled() || Flag.OPENCODE_DISABLE_TERMINAL_TITLE) return
if (route.data.type === "home") {
renderer.setTerminalTitle("OpenCode")
renderer.setTerminalTitle("TF Code")
return
}
if (route.data.type === "session") {
const session = sync.session.get(route.data.sessionID)
if (!session || SessionApi.isDefaultTitle(session.title)) {
renderer.setTerminalTitle("OpenCode")
renderer.setTerminalTitle("TF Code")
return
}
// Truncate title to 40 chars max
const title = session.title.length > 40 ? session.title.slice(0, 37) + "..." : session.title
renderer.setTerminalTitle(`OC | ${title}`)
renderer.setTerminalTitle(`TF | ${title}`)
}
})
@ -784,7 +784,7 @@ function App() {
await DialogAlert.show(
dialog,
"Update Complete",
`Successfully updated to OpenCode v${result.data.version}. Please restart the application.`,
`Successfully updated to TF Code v${result.data.version}. Please restart the application.`,
)
exit()

View File

@ -79,7 +79,7 @@ export function DialogStatus() {
<Match when={item.status === "failed" && item}>{(val) => val().error}</Match>
<Match when={item.status === "disabled"}>Disabled in configuration</Match>
<Match when={(item.status as string) === "needs_auth"}>
Needs authentication (run: opencode mcp auth {key})
Needs authentication (run: tfcode mcp auth {key})
</Match>
<Match when={(item.status as string) === "needs_client_registration" && item}>
{(val) => (val() as { error: string }).error}

View File

@ -253,7 +253,7 @@ export function Session() {
`${logo[3] ?? ""}`,
``,
` ${weak("Session")}${UI.Style.TEXT_NORMAL_BOLD}${title}${UI.Style.TEXT_NORMAL}`,
` ${weak("Continue")}${UI.Style.TEXT_NORMAL_BOLD}opencode -s ${session()?.id}${UI.Style.TEXT_NORMAL}`,
` ${weak("Continue")}${UI.Style.TEXT_NORMAL_BOLD}tfcode -s ${session()?.id}${UI.Style.TEXT_NORMAL}`,
``,
].join("\n"),
)

View File

@ -157,11 +157,11 @@ export function PermissionPrompt(props: { request: PermissionRequest }) {
body={
<Switch>
<Match when={props.request.always.length === 1 && props.request.always[0] === "*"}>
<TextBody title={"This will allow " + props.request.permission + " until OpenCode is restarted."} />
<TextBody title={"This will allow " + props.request.permission + " until TF Code is restarted."} />
</Match>
<Match when={true}>
<box paddingLeft={1} gap={1}>
<text fg={theme.textMuted}>This will allow the following patterns until OpenCode is restarted</text>
<text fg={theme.textMuted}>This will allow the following patterns until TF Code is restarted</text>
<box>
<For each={props.request.always}>
{(pattern) => (
@ -501,7 +501,7 @@ function RejectPrompt(props: { onConfirm: (message: string) => void; onCancel: (
<text fg={theme.text}>Reject permission</text>
</box>
<box paddingLeft={1}>
<text fg={theme.textMuted}>Tell OpenCode what to do differently</text>
<text fg={theme.textMuted}>Tell TF Code what to do differently</text>
</box>
</box>
<box

View File

@ -292,7 +292,7 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) {
</text>
</box>
<text fg={theme.textMuted}>OpenCode includes free models so you can start immediately.</text>
<text fg={theme.textMuted}>TF Code includes free models so you can start immediately.</text>
<text fg={theme.textMuted}>
Connect from 75+ providers to use other models, including Claude, GPT, Gemini etc
</text>

View File

@ -97,6 +97,7 @@ export namespace ModelsDev {
toolCalling: boolean
maxTokens: number
deprecated: boolean
deploymentType?: string
pricing?: {
inputPer1mTokens: number
outputPer1mTokens: number
@ -123,26 +124,26 @@ export namespace ModelsDev {
export async function get() {
const result = await Data()
const providers = result as Record<string, Provider>
// Try to fetch ToothFairyAI models dynamically
// First check env vars, then stored credentials
let tfApiKey = process.env.TF_API_KEY
let tfRegion = process.env.TF_REGION || "au"
// Try to load from stored credentials
if (!tfApiKey) {
try {
const credPath = path.join(Global.Path.data, ".tfcode", "credentials.json")
const credData = await Bun.file(credPath).json() as { api_key?: string; region?: string }
const credData = (await Bun.file(credPath).json()) as { api_key?: string; region?: string }
if (credData.api_key) {
tfApiKey = credData.api_key
tfRegion = credData.region || "au"
}
} catch {}
}
const tfBaseUrl = REGION_URLS[tfRegion] || REGION_URLS.au
if (tfApiKey) {
try {
const tfResponse = await fetch(`${tfBaseUrl}/models_list`, {
@ -151,16 +152,19 @@ export namespace ModelsDev {
},
signal: AbortSignal.timeout(10000),
})
if (tfResponse.ok) {
const tfData = await tfResponse.json() as { templates: Record<string, TFModel> }
const tfData = (await tfResponse.json()) as { templates: Record<string, TFModel> }
const tfModels: Record<string, Model> = {}
for (const [key, model] of Object.entries(tfData.templates || {})) {
if (model.deprecated) continue
// Only include serverless models
if (model.deploymentType && model.deploymentType !== "serverless") continue
const modelId = key.startsWith("z/") ? key.slice(2) : key
tfModels[modelId] = {
id: modelId,
name: model.name,
@ -185,7 +189,7 @@ export namespace ModelsDev {
},
}
}
providers["toothfairyai"] = {
id: "toothfairyai",
name: "ToothFairyAI",
@ -197,7 +201,7 @@ export namespace ModelsDev {
log.error("Failed to fetch ToothFairyAI models", { error: e })
}
}
// Fallback to static models if dynamic fetch failed
if (!providers["toothfairyai"] || Object.keys(providers["toothfairyai"].models).length === 0) {
providers["toothfairyai"] = {
@ -205,7 +209,7 @@ export namespace ModelsDev {
name: "ToothFairyAI",
env: ["TF_API_KEY", "TF_WORKSPACE_ID"],
models: {
"sorcerer": {
sorcerer: {
id: "sorcerer",
name: "TF Sorcerer",
family: "groq",
@ -219,7 +223,7 @@ export namespace ModelsDev {
limit: { context: 128000, output: 16000 },
modalities: { input: ["text", "image"], output: ["text"] },
},
"mystica": {
mystica: {
id: "mystica",
name: "TF Mystica",
family: "fireworks",
@ -236,7 +240,7 @@ export namespace ModelsDev {
},
}
}
return providers
}