From 8ecbe43e2dbab6143a36d1b99b2b6a9c7372ff01 Mon Sep 17 00:00:00 2001 From: Gab Date: Wed, 25 Mar 2026 09:35:02 +1100 Subject: [PATCH] feat: tfcode --- PROGRESS.md | 99 +++++++++++--------------- packages/tfcode/src/cli/cmd/upgrade.ts | 68 ++++-------------- packages/tfcode/src/flag/flag.ts | 2 +- 3 files changed, 55 insertions(+), 114 deletions(-) diff --git a/PROGRESS.md b/PROGRESS.md index f3ba03646..437c67533 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -17,74 +17,57 @@ Build and deploy **tfcode** - ToothFairyAI's official AI coding agent, a fork of - Postinstall script checks if binary exists before downloading - ESM-compatible module resolution for npm fallback - Wrapper script fixed to look for binary in correct location +8. ✅ Fixed ToothFairyAI model support (v1.0.5) + - Disabled `thinking` parameters for TF models (API doesn't support yet) + - Disabled auto-update (managed via npm instead) + - Updated `upgrade` command to point to npm + - Tested with `mystica` model - working! ## Current Status -**Working**: npm installation flow is now fully functional. Users can install via: +**Working**: npm installation and ToothFairyAI models are fully functional. ```bash -npm install @toothfairyai/tfcode -``` - -The binary is included in the main package, making installation instant without needing to download from Gitea or copy from optionalDependencies. - -## Next Steps - -1. Build all platform binaries (12 targets: linux/darwin/windows × arm64/x64 × baseline/musl) -2. Test on different platforms (currently only darwin-arm64 is tested) -3. Create Gitea releases for backup download mechanism -4. Consider making Gitea repo public for transparency - -## Technical Details - -### npm Package Structure - -The published package includes: - -- `bin/tfcode` - The actual binary (92MB) -- `bin/tfcode.js` - Wrapper script that spawns the binary -- `postinstall.mjs` - Installation script (checks for binary, downloads if missing, installs Python SDK) -- `package.json` - Package metadata -- `LICENSE` - MIT license - -### Installation Flow - -1. npm installs main package + optionalDependencies -2. npm extracts files to `node_modules/@toothfairyai/tfcode/` -3. postinstall runs: - - Checks if binary already exists (✓ for darwin-arm64) - - If not, tries to download from Gitea - - If that fails, copies from optionalDependencies - - Installs Python SDK for TF integration -4. User can run `tfcode` command - -### Key Fixes in v1.0.4 - -1. **Postinstall script**: Fixed duplicate variable declaration (`binaryName`) -2. **Postinstall script**: Added early return if binary already exists -3. **Postinstall script**: Fixed ESM module resolution (replaced `require.resolve` with `import.meta.resolve`) -4. **Publish script**: Copy current platform binary to main package -5. **Wrapper script**: Fixed binary path (removed extra `bin/` directory) - -## Testing - -```bash -# Fresh installation test -rm -rf /tmp/tfcode-test && mkdir /tmp/tfcode-test -cd /tmp/tfcode-test && npm init -y -npm install @toothfairyai/tfcode -node_modules/.bin/tfcode --version # Should output: 1.0.4 +npm install -g @toothfairyai/tfcode@latest ``` ## Version History +- **1.0.5**: Fixed ToothFairyAI model support, disabled auto-update - **1.0.4**: Fixed npm installation flow, binary included in main package - **1.0.3**: Initial npm publication (broken installation) -- **1.0.2**: Earlier testing versions -- **1.0.0**: Initial release -## Credentials (Testing Only) +## Key Fixes -- workspace_id: `6586b7e6-683e-4ee6-a6cf-24c19729b5ff` -- api_key: `EWZooLROIS57EVW3BKGu7Pv6LNe4D6m4gkDjukx3` -- region: `dev` +### v1.0.5 Changes + +1. **Provider transform**: Added early return for `@toothfairyai/sdk` to prevent sending `thinking` parameters +2. **Auto-update**: Hardcoded `OPENCODE_DISABLE_AUTOUPDATE = true` +3. **Upgrade command**: Now shows npm instructions instead of attempting self-update + +### v1.0.4 Changes + +1. **Postinstall script**: Fixed ESM module resolution, early return if binary exists +2. **Publish script**: Copy current platform binary to main package +3. **Wrapper script**: Fixed binary path lookup + +## Testing + +```bash +# Install +npm install -g @toothfairyai/tfcode@latest + +# Set credentials +export TF_WORKSPACE_ID="your-workspace-id" +export TF_API_KEY="your-api-key" +export TF_REGION="dev" # or au, eu, us + +# Test +tfcode run "say hello" --model toothfairyai/mystica +``` + +## Next Steps + +1. Build all platform binaries (12 targets) +2. Test on different platforms (currently only darwin-arm64) +3. Document available models (mystica, mystica_15, etc.) diff --git a/packages/tfcode/src/cli/cmd/upgrade.ts b/packages/tfcode/src/cli/cmd/upgrade.ts index 4412d558b..98514461a 100644 --- a/packages/tfcode/src/cli/cmd/upgrade.ts +++ b/packages/tfcode/src/cli/cmd/upgrade.ts @@ -1,73 +1,31 @@ import type { Argv } from "yargs" import { UI } from "../ui" import * as prompts from "@clack/prompts" -import { Installation } from "../../installation" export const UpgradeCommand = { command: "upgrade [target]", describe: "upgrade tfcode to the latest or a specific version", builder: (yargs: Argv) => { - return yargs - .positional("target", { - describe: "version to upgrade to, for ex '0.1.48' or 'v0.1.48'", - type: "string", - }) - .option("method", { - alias: "m", - describe: "installation method to use", - type: "string", - choices: ["curl", "npm", "pnpm", "bun", "brew", "choco", "scoop"], - }) + return yargs.positional("target", { + describe: "version to upgrade to, for ex '1.0.5' or 'v1.0.5'", + type: "string", + }) }, - handler: async (args: { target?: string; method?: string }) => { + handler: async (args: { target?: string }) => { UI.empty() UI.println(UI.logo(" ")) UI.empty() prompts.intro("Upgrade") - const detectedMethod = await Installation.method() - const method = (args.method as Installation.Method) ?? detectedMethod - if (method === "unknown") { - prompts.log.error(`tfcode is installed to ${process.execPath} and may be managed by a package manager`) - const install = await prompts.select({ - message: "Install anyways?", - options: [ - { label: "Yes", value: true }, - { label: "No", value: false }, - ], - initialValue: false, - }) - if (!install) { - prompts.outro("Done") - return - } - } - prompts.log.info("Using method: " + method) - const target = args.target ? args.target.replace(/^v/, "") : await Installation.latest() - if (Installation.VERSION === target) { - prompts.log.warn(`tfcode upgrade skipped: ${target} is already installed`) - prompts.outro("Done") - return - } + prompts.log.info("tfcode is managed via npm.") + prompts.log.info("To upgrade, run:") + prompts.log.info("") + prompts.log.info(" npm install -g @toothfairyai/tfcode@latest") + prompts.log.info("") + prompts.log.info("Or for a specific version:") + prompts.log.info("") + prompts.log.info(` npm install -g @toothfairyai/tfcode@${args.target || "1.0.5"}`) - prompts.log.info(`From ${Installation.VERSION} → ${target}`) - const spinner = prompts.spinner() - spinner.start("Upgrading...") - const err = await Installation.upgrade(method, target).catch((err) => err) - if (err) { - spinner.stop("Upgrade failed", 1) - if (err instanceof Installation.UpgradeFailedError) { - // necessary because choco only allows install/upgrade in elevated terminals - if (method === "choco" && err.stderr.includes("not running from an elevated command shell")) { - prompts.log.error("Please run the terminal as Administrator and try again") - } else { - prompts.log.error(err.stderr) - } - } else if (err instanceof Error) prompts.log.error(err.message) - prompts.outro("Done") - return - } - spinner.stop("Upgrade complete") prompts.outro("Done") }, } diff --git a/packages/tfcode/src/flag/flag.ts b/packages/tfcode/src/flag/flag.ts index 0c55187b9..70e66589e 100644 --- a/packages/tfcode/src/flag/flag.ts +++ b/packages/tfcode/src/flag/flag.ts @@ -17,7 +17,7 @@ export namespace Flag { export declare const OPENCODE_TUI_CONFIG: string | undefined export declare const OPENCODE_CONFIG_DIR: string | undefined export const OPENCODE_CONFIG_CONTENT = process.env["OPENCODE_CONFIG_CONTENT"] - export const OPENCODE_DISABLE_AUTOUPDATE = truthy("OPENCODE_DISABLE_AUTOUPDATE") + export const OPENCODE_DISABLE_AUTOUPDATE = true // Disabled for tfcode - updates managed via npm export const OPENCODE_ALWAYS_NOTIFY_UPDATE = truthy("OPENCODE_ALWAYS_NOTIFY_UPDATE") export const OPENCODE_DISABLE_PRUNE = truthy("OPENCODE_DISABLE_PRUNE") export const OPENCODE_DISABLE_TERMINAL_TITLE = truthy("OPENCODE_DISABLE_TERMINAL_TITLE")