@toothfairyai/tfcode 3.0.4 → 3.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,170 +1,33 @@
1
1
  {
2
- "$schema": "https://json.schemastore.org/package.json",
3
- "version": "3.0.4",
4
2
  "name": "@toothfairyai/tfcode",
5
- "type": "module",
6
- "license": "MIT",
7
- "files": [
8
- "bin",
9
- "app",
10
- "postinstall.mjs",
11
- "LICENSE"
12
- ],
13
- "scripts": {
14
- "prepare": "effect-language-service patch || true",
15
- "postinstall": "node scripts/postinstall.cjs",
16
- "typecheck": "tsgo --noEmit",
17
- "test": "bun test --timeout 30000",
18
- "build": "bun run script/build-tfcode.ts",
19
- "build:single": "bun run script/build-tfcode.ts --single",
20
- "publish:upload": "bun run script/publish-tfcode.ts --upload",
21
- "publish:npm": "bun run script/publish-tfcode.ts --npm",
22
- "publish:brew": "bun run script/publish-tfcode.ts --brew",
23
- "publish:all": "bun run script/publish-tfcode.ts --all",
24
- "dev": "bun run --conditions=browser ./src/index.ts",
25
- "db": "bun drizzle-kit"
26
- },
3
+ "version": "3.0.5",
27
4
  "bin": {
28
- "tfcode": "./bin/tfcode"
5
+ "tfcode": "./bin/tfcode.js"
29
6
  },
30
- "exports": {
31
- "./*": "./src/*.ts"
32
- },
33
- "imports": {
34
- "#db": {
35
- "bun": "./src/storage/db.bun.ts",
36
- "node": "./src/storage/db.node.ts",
37
- "default": "./src/storage/db.bun.ts"
38
- }
7
+ "scripts": {
8
+ "postinstall": "node ./postinstall.mjs"
39
9
  },
40
- "devDependencies": {
41
- "@babel/core": "7.28.4",
42
- "@effect/language-service": "0.79.0",
43
- "@octokit/webhooks-types": "7.6.1",
44
- "@opencode-ai/script": "workspace:*",
45
- "@parcel/watcher-darwin-arm64": "2.5.1",
46
- "@parcel/watcher-darwin-x64": "2.5.1",
47
- "@parcel/watcher-linux-arm64-glibc": "2.5.1",
48
- "@parcel/watcher-linux-arm64-musl": "2.5.1",
49
- "@parcel/watcher-linux-x64-glibc": "2.5.1",
50
- "@parcel/watcher-linux-x64-musl": "2.5.1",
51
- "@parcel/watcher-win32-arm64": "2.5.1",
52
- "@parcel/watcher-win32-x64": "2.5.1",
53
- "@standard-schema/spec": "1.0.0",
54
- "@tsconfig/bun": "catalog:",
55
- "@types/babel__core": "7.20.5",
56
- "@types/bun": "1.3.11",
57
- "@types/cross-spawn": "6.0.6",
58
- "@types/mime-types": "3.0.1",
59
- "@types/node": "22.13.9",
60
- "@types/semver": "^7.5.8",
61
- "@types/turndown": "5.0.5",
62
- "@types/which": "3.0.4",
63
- "@types/ws": "8.18.1",
64
- "@types/yargs": "17.0.33",
65
- "@typescript/native-preview": "catalog:",
66
- "drizzle-kit": "catalog:",
67
- "drizzle-orm": "catalog:",
68
- "typescript": "catalog:",
69
- "vscode-languageserver-types": "3.17.5",
70
- "why-is-node-running": "3.2.2",
71
- "zod-to-json-schema": "3.24.5"
10
+ "license": "MIT",
11
+ "optionalDependencies": {
12
+ "@toothfairyai/tfcode-linux-arm64": "3.0.5",
13
+ "@toothfairyai/tfcode-windows-x64": "3.0.5",
14
+ "@toothfairyai/tfcode-linux-x64-baseline-musl": "3.0.5",
15
+ "@toothfairyai/tfcode-darwin-x64-baseline": "3.0.5",
16
+ "@toothfairyai/tfcode-linux-x64-musl": "3.0.5",
17
+ "@toothfairyai/tfcode-windows-x64-baseline": "3.0.5",
18
+ "@toothfairyai/tfcode-linux-arm64-musl": "3.0.5",
19
+ "@toothfairyai/tfcode-windows-arm64": "3.0.5",
20
+ "@toothfairyai/tfcode-linux-x64": "3.0.5",
21
+ "@toothfairyai/tfcode-darwin-x64": "3.0.5",
22
+ "@toothfairyai/tfcode-linux-x64-baseline": "3.0.5",
23
+ "@toothfairyai/tfcode-darwin-arm64": "3.0.5"
72
24
  },
73
- "dependencies": {
74
- "@actions/core": "1.11.1",
75
- "@actions/github": "6.0.1",
76
- "@agentclientprotocol/sdk": "0.14.1",
77
- "@ai-sdk/amazon-bedrock": "3.0.82",
78
- "@ai-sdk/anthropic": "2.0.65",
79
- "@ai-sdk/azure": "2.0.91",
80
- "@ai-sdk/cerebras": "1.0.36",
81
- "@ai-sdk/cohere": "2.0.22",
82
- "@ai-sdk/deepinfra": "1.0.36",
83
- "@ai-sdk/gateway": "2.0.30",
84
- "@ai-sdk/google": "2.0.54",
85
- "@ai-sdk/google-vertex": "3.0.106",
86
- "@ai-sdk/groq": "2.0.34",
87
- "@ai-sdk/mistral": "2.0.27",
88
- "@ai-sdk/openai": "2.0.89",
89
- "@ai-sdk/openai-compatible": "1.0.32",
90
- "@ai-sdk/perplexity": "2.0.23",
91
- "@ai-sdk/provider": "2.0.1",
92
- "@ai-sdk/provider-utils": "3.0.21",
93
- "@ai-sdk/togetherai": "1.0.34",
94
- "@ai-sdk/vercel": "1.0.33",
95
- "@ai-sdk/xai": "2.0.51",
96
- "@aws-sdk/credential-providers": "3.993.0",
97
- "@clack/prompts": "1.0.0-alpha.1",
98
- "@effect/platform-node": "catalog:",
99
- "@hono/standard-validator": "0.1.5",
100
- "@hono/zod-validator": "catalog:",
101
- "@modelcontextprotocol/sdk": "1.29.0",
102
- "@octokit/graphql": "9.0.2",
103
- "@octokit/rest": "catalog:",
104
- "@openauthjs/openauth": "catalog:",
105
- "@opencode-ai/gateway": "workspace:*",
106
- "@opencode-ai/plugin": "workspace:*",
107
- "@opencode-ai/script": "workspace:*",
108
- "@opencode-ai/sdk": "workspace:*",
109
- "@opencode-ai/util": "workspace:*",
110
- "@openrouter/ai-sdk-provider": "1.5.4",
111
- "@opentui/core": "0.2.16",
112
- "@opentui/solid": "0.2.16",
113
- "@parcel/watcher": "2.5.1",
114
- "@pierre/diffs": "catalog:",
115
- "@solid-primitives/event-bus": "1.1.2",
116
- "@solid-primitives/scheduled": "1.5.2",
117
- "@standard-schema/spec": "1.0.0",
118
- "@zip.js/zip.js": "2.7.62",
119
- "ai": "catalog:",
120
- "ai-gateway-provider": "2.3.1",
121
- "bonjour-service": "1.3.0",
122
- "bun-pty": "0.4.8",
123
- "chokidar": "4.0.3",
124
- "clipboardy": "4.0.0",
125
- "croner": "10.0.1",
126
- "cross-spawn": "^7.0.6",
127
- "decimal.js": "10.5.0",
128
- "diff": "catalog:",
129
- "drizzle-orm": "catalog:",
130
- "effect": "catalog:",
131
- "fuzzysort": "3.1.0",
132
- "gitlab-ai-provider": "5.2.2",
133
- "glob": "13.0.5",
134
- "google-auth-library": "10.5.0",
135
- "gray-matter": "4.0.3",
136
- "hono": "catalog:",
137
- "hono-openapi": "catalog:",
138
- "ignore": "7.0.5",
139
- "jsonc-parser": "3.3.1",
140
- "jszip": "3.10.2",
141
- "marked": "catalog:",
142
- "mime-types": "3.0.2",
143
- "minimatch": "10.0.3",
144
- "open": "10.1.2",
145
- "opencode-gitlab-auth": "2.0.0",
146
- "opentui-spinner": "0.0.6",
147
- "partial-json": "0.1.7",
148
- "react": "19.2.4",
149
- "react-dom": "19.2.4",
150
- "remeda": "catalog:",
151
- "semver": "^7.6.3",
152
- "solid-js": "catalog:",
153
- "strip-ansi": "7.1.2",
154
- "tree-sitter-bash": "0.25.0",
155
- "tree-sitter-powershell": "0.25.10",
156
- "turndown": "7.2.0",
157
- "ulid": "catalog:",
158
- "vscode-jsonrpc": "8.2.1",
159
- "web-tree-sitter": "0.25.10",
160
- "which": "6.0.1",
161
- "ws": "8.21.0",
162
- "xdg-basedir": "5.1.0",
163
- "yargs": "18.0.0",
164
- "zod": "catalog:",
165
- "zod-to-json-schema": "3.24.5"
25
+ "engines": {
26
+ "node": ">=18"
166
27
  },
167
- "overrides": {
168
- "drizzle-orm": "catalog:"
28
+ "homepage": "https://toothfairyai.com/developers/tfcode",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git"
169
32
  }
170
- }
33
+ }
@@ -0,0 +1,236 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "fs"
4
+ import path from "path"
5
+ import os from "os"
6
+ import { spawnSync } from "child_process"
7
+ import { fileURLToPath } from "url"
8
+
9
+ const __filename = fileURLToPath(import.meta.url)
10
+ const __dirname = path.dirname(__filename)
11
+
12
+ function detectPlatform() {
13
+ let platform
14
+ switch (os.platform()) {
15
+ case "darwin":
16
+ platform = "darwin"
17
+ break
18
+ case "linux":
19
+ platform = "linux"
20
+ break
21
+ case "win32":
22
+ platform = "windows"
23
+ break
24
+ default:
25
+ platform = os.platform()
26
+ }
27
+
28
+ let arch
29
+ switch (os.arch()) {
30
+ case "x64":
31
+ arch = "x64"
32
+ break
33
+ case "arm64":
34
+ arch = "arm64"
35
+ break
36
+ default:
37
+ arch = os.arch()
38
+ }
39
+
40
+ // Check for AVX2 on x64
41
+ let needsBaseline = false
42
+ if (arch === "x64" && (platform === "linux" || platform === "darwin")) {
43
+ try {
44
+ if (platform === "linux") {
45
+ const cpuinfo = fs.readFileSync("/proc/cpuinfo", "utf8")
46
+ needsBaseline = !cpuinfo.toLowerCase().includes("avx2")
47
+ } else if (platform === "darwin") {
48
+ const result = spawnSync("sysctl", ["-n", "hw.optional.avx2_0"], { encoding: "utf8" })
49
+ needsBaseline = result.stdout.trim() !== "1"
50
+ }
51
+ } catch {}
52
+ }
53
+
54
+ // Check for musl on Linux
55
+ let abi = ""
56
+ if (platform === "linux") {
57
+ try {
58
+ if (fs.existsSync("/etc/alpine-release")) {
59
+ abi = "musl"
60
+ } else {
61
+ const result = spawnSync("ldd", ["--version"], { encoding: "utf8" })
62
+ if ((result.stdout + result.stderr).toLowerCase().includes("musl")) {
63
+ abi = "musl"
64
+ }
65
+ }
66
+ } catch {}
67
+ }
68
+
69
+ return { platform, arch, needsBaseline, abi }
70
+ }
71
+
72
+ function targetName() {
73
+ const { platform, arch, needsBaseline, abi } = detectPlatform()
74
+ let target = `tfcode-${platform}-${arch}`
75
+ if (needsBaseline) target += "-baseline"
76
+ if (abi) target += `-${abi}`
77
+ return target
78
+ }
79
+
80
+ // Copy bundled computer-use helper binaries (e.g. cliclick on macOS) from a
81
+ // source bin dir into the installed bin dir, so `tfcode computer setup` finds
82
+ // them next to the binary without Homebrew/apt. No-op when absent. npm may
83
+ // strip the exec bit, so chmod the helpers back to 0755.
84
+ function copyComputerAssets(srcBinDir, dstBinDir) {
85
+ const srcComputer = path.join(srcBinDir, "computer")
86
+ if (!fs.existsSync(srcComputer)) return
87
+ const dstComputer = path.join(dstBinDir, "computer")
88
+ if (fs.existsSync(dstComputer)) fs.rmSync(dstComputer, { recursive: true, force: true })
89
+ fs.cpSync(srcComputer, dstComputer, { recursive: true })
90
+ for (const name of fs.readdirSync(dstComputer)) {
91
+ try {
92
+ fs.chmodSync(path.join(dstComputer, name), 0o755)
93
+ } catch {}
94
+ }
95
+ console.log("✓ Computer-use helpers copied from platform package")
96
+ }
97
+
98
+ // The binary ships in the platform-specific optionalDependency
99
+ // (@toothfairyai/tfcode-<platform>-<arch>[-baseline][-musl]). Link it into
100
+ // this package's bin/ dir and copy the web app + computer-use helpers.
101
+ function setupFromPlatformPackage() {
102
+ const { platform } = detectPlatform()
103
+ const pkgName = `@toothfairyai/${targetName()}`
104
+ const binaryName = platform === "windows" ? "tfcode.exe" : "tfcode"
105
+ const binDir = path.join(__dirname, "bin")
106
+
107
+ // ESM-compatible module resolution
108
+ let pkgDir
109
+ try {
110
+ const pkgUrl = import.meta.resolve(`${pkgName}/package.json`)
111
+ const pkgPath = fileURLToPath(pkgUrl)
112
+ pkgDir = path.dirname(pkgPath)
113
+ } catch (e) {
114
+ console.error(`Could not resolve ${pkgName}: ${e.message}`)
115
+ console.error("")
116
+ console.error("The platform package for your machine was not installed.")
117
+ console.error("")
118
+ console.error("Possible solutions:")
119
+ console.error(` 1. Install it explicitly: npm install ${pkgName}`)
120
+ console.error(" 2. Clear the npm cache and reinstall: npm cache clean --force && npm install @toothfairyai/tfcode")
121
+ console.error(" 3. Contact ToothFairyAI support for assistance")
122
+ console.error("")
123
+ process.exit(1)
124
+ }
125
+
126
+ const sourceBinary = path.join(pkgDir, "bin", binaryName)
127
+ if (!fs.existsSync(sourceBinary)) {
128
+ console.error(`Binary not found at ${sourceBinary}`)
129
+ process.exit(1)
130
+ }
131
+
132
+ // Link (or copy) the binary into bin/
133
+ if (!fs.existsSync(binDir)) fs.mkdirSync(binDir, { recursive: true })
134
+ const targetBinary = path.join(binDir, binaryName)
135
+ if (fs.existsSync(targetBinary)) fs.unlinkSync(targetBinary)
136
+ try {
137
+ fs.linkSync(sourceBinary, targetBinary)
138
+ } catch {
139
+ fs.copyFileSync(sourceBinary, targetBinary)
140
+ }
141
+ fs.chmodSync(targetBinary, 0o755)
142
+ console.log(`tfcode installed to ${targetBinary}`)
143
+
144
+ // Copy app dir
145
+ const srcAppDir = path.join(pkgDir, "bin", "app")
146
+ const targetAppDir = path.join(binDir, "app")
147
+ if (fs.existsSync(path.join(srcAppDir, "dist", "index.html"))) {
148
+ if (fs.existsSync(targetAppDir)) fs.rmSync(targetAppDir, { recursive: true, force: true })
149
+ fs.cpSync(srcAppDir, targetAppDir, { recursive: true })
150
+ console.log("Web app copied from platform package")
151
+ } else {
152
+ console.log("! Web app not found in platform package")
153
+ }
154
+
155
+ copyComputerAssets(path.join(pkgDir, "bin"), binDir)
156
+ }
157
+
158
+ async function main() {
159
+ console.log("")
160
+ console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
161
+ console.log(" tfcode - ToothFairyAI's official coding agent")
162
+ console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
163
+ console.log("")
164
+
165
+ // Setup binary from the npm platform package
166
+ setupFromPlatformPackage()
167
+
168
+ // Check for Python (needed for TF integration)
169
+ try {
170
+ const result = spawnSync("python3", ["--version"], { encoding: "utf8" })
171
+ if (result.status === 0) {
172
+ console.log(`✓ Found ${result.stdout.trim()}`)
173
+
174
+ // Install Python SDK
175
+ console.log("Installing ToothFairyAI Python SDK...")
176
+ const pipResult = spawnSync(
177
+ "python3",
178
+ ["-m", "pip", "install", "--user", "--break-system-packages", "toothfairyai", "pydantic", "httpx", "rich"],
179
+ {
180
+ stdio: "inherit",
181
+ },
182
+ )
183
+
184
+ if (pipResult.status === 0) {
185
+ console.log("✓ Python SDK installed")
186
+ } else {
187
+ console.log("! Python SDK install failed, run manually:")
188
+ console.log(" pip install toothfairyai pydantic httpx rich")
189
+ }
190
+ }
191
+ } catch {
192
+ console.log("! Python 3.10+ not found. Install with:")
193
+ console.log(" macOS: brew install python@3.12")
194
+ console.log(" Ubuntu: sudo apt install python3.12")
195
+ console.log(" Windows: Download from python.org/downloads")
196
+ console.log("")
197
+ }
198
+
199
+ console.log("")
200
+ console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
201
+ console.log("✓ tfcode installed successfully!")
202
+ console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
203
+ console.log("")
204
+ console.log("Quick Start:")
205
+ console.log("")
206
+ console.log(" 1. Set credentials:")
207
+ console.log(' export TF_WORKSPACE_ID="your-workspace-id"')
208
+ console.log(' export TF_API_KEY="your-api-key"')
209
+ console.log("")
210
+ console.log(" 2. Validate:")
211
+ console.log(" tfcode validate")
212
+ console.log("")
213
+ console.log(" 3. Sync tools:")
214
+ console.log(" tfcode sync")
215
+ console.log("")
216
+ console.log(" 4. Start coding:")
217
+ console.log(" tfcode")
218
+ console.log("")
219
+ // Optional feature — keep it short and clearly labeled so the coding-first
220
+ // Quick Start isn't noised up. Point npm installers at the one-command setup.
221
+ const cuPlatform = os.platform()
222
+ const cuHint =
223
+ cuPlatform === "darwin"
224
+ ? "a permissions dialog will appear (Accessibility & Screen Recording); cliclick is bundled."
225
+ : cuPlatform === "win32"
226
+ ? "no extra installs needed — pre-compiles the input helper."
227
+ : "installs xdotool + a screenshot tool via your package manager."
228
+ console.log(" Computer use (optional — control the OS GUI: mouse, keyboard, screen):")
229
+ console.log(" tfcode computer setup " + cuHint)
230
+ console.log(" tfcode computer doctor verify it works")
231
+ console.log("")
232
+ console.log("Documentation: https://toothfairyai.com/developers/tfcode")
233
+ console.log("")
234
+ }
235
+
236
+ main().catch(console.error)
@@ -0,0 +1,21 @@
1
+ """
2
+ tf-sync: ToothFairyAI workspace sync layer for tfcode
3
+ """
4
+
5
+ from tf_sync.agents import sync_agents
6
+ from tf_sync.mcp import sync_mcp_servers
7
+ from tf_sync.tools import sync_tools, ToolType
8
+ from tf_sync.config import TFConfig, load_config, validate_credentials, get_region_urls
9
+
10
+ __all__ = [
11
+ "sync_agents",
12
+ "sync_mcp_servers",
13
+ "sync_tools",
14
+ "ToolType",
15
+ "TFConfig",
16
+ "load_config",
17
+ "validate_credentials",
18
+ "get_region_urls",
19
+ ]
20
+
21
+ __version__ = "0.1.0"
@@ -0,0 +1,39 @@
1
+ """
2
+ Agent sync module for tfcode.
3
+
4
+ NOTE: This module is reserved for future implementation.
5
+ Currently, tfcode only syncs tools (MCP, Skills, Database, Functions).
6
+ Agent sync will be added in a later phase.
7
+ """
8
+
9
+ from typing import Any
10
+
11
+ from pydantic import BaseModel
12
+
13
+ from tf_sync.config import TFConfig
14
+
15
+
16
+ class AgentSyncResult(BaseModel):
17
+ """Result of agent sync operation."""
18
+
19
+ success: bool
20
+ agents: list[dict[str, Any]] = []
21
+ error: str | None = None
22
+
23
+
24
+ def sync_agents(config: TFConfig) -> AgentSyncResult:
25
+ """
26
+ Sync agents from ToothFairyAI workspace.
27
+
28
+ NOTE: Currently not implemented. Reserved for future use.
29
+
30
+ Args:
31
+ config: TFConfig instance
32
+
33
+ Returns:
34
+ AgentSyncResult (currently always returns not implemented)
35
+ """
36
+ return AgentSyncResult(
37
+ success=False,
38
+ error="Agent sync not yet implemented. Use tools sync for now.",
39
+ )