@toothfairyai/tfcode 1.0.0-beta.8 → 1.0.0
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/LICENSE +21 -0
- package/bin/tfcode.js +168 -569
- package/package.json +19 -19
- package/postinstall.mjs +232 -0
- package/README.md +0 -146
- package/scripts/postinstall.cjs +0 -171
- package/scripts/quickstart.cjs +0 -66
package/package.json
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toothfairyai/tfcode",
|
|
3
|
-
"version": "1.0.0
|
|
4
|
-
"description": "ToothFairyAI's official AI coding agent",
|
|
5
|
-
"keywords": ["toothfairyai", "ai", "coding", "cli"],
|
|
6
|
-
"author": "ToothFairyAI",
|
|
7
|
-
"license": "MIT",
|
|
8
|
-
"type": "module",
|
|
3
|
+
"version": "1.0.0",
|
|
9
4
|
"bin": {
|
|
10
|
-
"tfcode": "./bin/tfcode
|
|
5
|
+
"tfcode": "./bin/tfcode"
|
|
11
6
|
},
|
|
12
|
-
"files": [
|
|
13
|
-
"bin/",
|
|
14
|
-
"scripts/"
|
|
15
|
-
],
|
|
16
7
|
"scripts": {
|
|
17
|
-
"postinstall": "node
|
|
18
|
-
},
|
|
19
|
-
"dependencies": {
|
|
20
|
-
"yargs": "^17.7.2"
|
|
8
|
+
"postinstall": "node ./postinstall.mjs"
|
|
21
9
|
},
|
|
22
|
-
"
|
|
23
|
-
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"optionalDependencies": {
|
|
12
|
+
"@toothfairyai/tfcode-linux-arm64": "1.0.0",
|
|
13
|
+
"@toothfairyai/tfcode-windows-x64": "1.0.0",
|
|
14
|
+
"@toothfairyai/tfcode-linux-x64-baseline-musl": "1.0.0",
|
|
15
|
+
"@toothfairyai/tfcode-darwin-x64-baseline": "1.0.0",
|
|
16
|
+
"@toothfairyai/tfcode-linux-x64-musl": "1.0.0",
|
|
17
|
+
"@toothfairyai/tfcode-windows-x64-baseline": "1.0.0",
|
|
18
|
+
"@toothfairyai/tfcode-linux-arm64-musl": "1.0.0",
|
|
19
|
+
"@toothfairyai/tfcode-windows-arm64": "1.0.0",
|
|
20
|
+
"@toothfairyai/tfcode-linux-x64": "1.0.0",
|
|
21
|
+
"@toothfairyai/tfcode-darwin-x64": "1.0.0",
|
|
22
|
+
"@toothfairyai/tfcode-linux-x64-baseline": "1.0.0",
|
|
23
|
+
"@toothfairyai/tfcode-darwin-arm64": "1.0.0"
|
|
24
24
|
},
|
|
25
25
|
"homepage": "https://toothfairyai.com/developers/tfcode",
|
|
26
26
|
"repository": {
|
|
27
27
|
"type": "git",
|
|
28
|
-
"url": "https://
|
|
28
|
+
"url": "https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git"
|
|
29
29
|
}
|
|
30
|
-
}
|
|
30
|
+
}
|
package/postinstall.mjs
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
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
|
+
|
|
8
|
+
const GITEA_HOST = process.env.TFCODE_GITEA_HOST || "gitea.toothfairyai.com"
|
|
9
|
+
const GITEA_REPO = process.env.TFCODE_GITEA_REPO || "ToothFairyAI/tf_code"
|
|
10
|
+
|
|
11
|
+
function detectPlatform() {
|
|
12
|
+
let platform
|
|
13
|
+
switch (os.platform()) {
|
|
14
|
+
case "darwin":
|
|
15
|
+
platform = "darwin"
|
|
16
|
+
break
|
|
17
|
+
case "linux":
|
|
18
|
+
platform = "linux"
|
|
19
|
+
break
|
|
20
|
+
case "win32":
|
|
21
|
+
platform = "windows"
|
|
22
|
+
break
|
|
23
|
+
default:
|
|
24
|
+
platform = os.platform()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let arch
|
|
28
|
+
switch (os.arch()) {
|
|
29
|
+
case "x64":
|
|
30
|
+
arch = "x64"
|
|
31
|
+
break
|
|
32
|
+
case "arm64":
|
|
33
|
+
arch = "arm64"
|
|
34
|
+
break
|
|
35
|
+
default:
|
|
36
|
+
arch = os.arch()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Check for AVX2 on x64
|
|
40
|
+
let needsBaseline = false
|
|
41
|
+
if (arch === "x64" && (platform === "linux" || platform === "darwin")) {
|
|
42
|
+
try {
|
|
43
|
+
if (platform === "linux") {
|
|
44
|
+
const cpuinfo = fs.readFileSync("/proc/cpuinfo", "utf8")
|
|
45
|
+
needsBaseline = !cpuinfo.toLowerCase().includes("avx2")
|
|
46
|
+
} else if (platform === "darwin") {
|
|
47
|
+
const result = spawnSync("sysctl", ["-n", "hw.optional.avx2_0"], { encoding: "utf8" })
|
|
48
|
+
needsBaseline = result.stdout.trim() !== "1"
|
|
49
|
+
}
|
|
50
|
+
} catch {}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Check for musl on Linux
|
|
54
|
+
let abi = ""
|
|
55
|
+
if (platform === "linux") {
|
|
56
|
+
try {
|
|
57
|
+
if (fs.existsSync("/etc/alpine-release")) {
|
|
58
|
+
abi = "musl"
|
|
59
|
+
} else {
|
|
60
|
+
const result = spawnSync("ldd", ["--version"], { encoding: "utf8" })
|
|
61
|
+
if ((result.stdout + result.stderr).toLowerCase().includes("musl")) {
|
|
62
|
+
abi = "musl"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
} catch {}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return { platform, arch, needsBaseline, abi }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function getVersion() {
|
|
72
|
+
try {
|
|
73
|
+
const res = await fetch(`https://${GITEA_HOST}/api/v1/repos/${GITEA_REPO}/releases/latest`)
|
|
74
|
+
const data = await res.json()
|
|
75
|
+
return data.tag_name?.replace(/^v/, "") || "1.0.0"
|
|
76
|
+
} catch {
|
|
77
|
+
return "1.0.0"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function downloadBinary() {
|
|
82
|
+
const { platform, arch, needsBaseline, abi } = detectPlatform()
|
|
83
|
+
const version = await getVersion()
|
|
84
|
+
|
|
85
|
+
// Build filename
|
|
86
|
+
let target = `tfcode-${platform}-${arch}`
|
|
87
|
+
if (needsBaseline) target += "-baseline"
|
|
88
|
+
if (abi) target += `-${abi}`
|
|
89
|
+
|
|
90
|
+
const ext = platform === "linux" ? ".tar.gz" : ".zip"
|
|
91
|
+
const filename = `${target}${ext}`
|
|
92
|
+
const url = `https://${GITEA_HOST}/${GITEA_REPO}/releases/download/v${version}/${filename}`
|
|
93
|
+
|
|
94
|
+
console.log(`Downloading tfcode v${version} for ${target}...`)
|
|
95
|
+
|
|
96
|
+
// Download
|
|
97
|
+
const binDir = path.join(__dirname, "bin")
|
|
98
|
+
if (!fs.existsSync(binDir)) fs.mkdirSync(binDir, { recursive: true })
|
|
99
|
+
|
|
100
|
+
const tmpDir = path.join(os.tmpdir(), `tfcode-install-${process.pid}`)
|
|
101
|
+
fs.mkdirSync(tmpDir, { recursive: true })
|
|
102
|
+
const archivePath = path.join(tmpDir, filename)
|
|
103
|
+
|
|
104
|
+
// Use curl to download
|
|
105
|
+
const curlResult = spawnSync("curl", ["-fsSL", "-o", archivePath, url], { stdio: "inherit" })
|
|
106
|
+
if (curlResult.status !== 0) {
|
|
107
|
+
console.error(`Failed to download from ${url}`)
|
|
108
|
+
console.error("Trying npm package fallback...")
|
|
109
|
+
|
|
110
|
+
// Fallback to npm optionalDependencies
|
|
111
|
+
try {
|
|
112
|
+
const pkgName = `@toothfairyai/${target}`
|
|
113
|
+
const pkgPath = require.resolve(`${pkgName}/package.json`)
|
|
114
|
+
const pkgDir = path.dirname(pkgPath)
|
|
115
|
+
const binaryName = platform === "windows" ? "tfcode.exe" : "tfcode"
|
|
116
|
+
const binaryPath = path.join(pkgDir, "bin", binaryName)
|
|
117
|
+
|
|
118
|
+
if (fs.existsSync(binaryPath)) {
|
|
119
|
+
setupBinary(binaryPath, platform)
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
} catch {}
|
|
123
|
+
|
|
124
|
+
process.exit(1)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Extract
|
|
128
|
+
console.log("Extracting...")
|
|
129
|
+
if (platform === "linux") {
|
|
130
|
+
spawnSync("tar", ["-xzf", archivePath, "-C", tmpDir], { stdio: "inherit" })
|
|
131
|
+
} else {
|
|
132
|
+
spawnSync("unzip", ["-q", archivePath, "-d", tmpDir], { stdio: "inherit" })
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Move binary
|
|
136
|
+
const binaryName = platform === "windows" ? "tfcode.exe" : "tfcode"
|
|
137
|
+
const extractedBinary = path.join(tmpDir, "tfcode")
|
|
138
|
+
const targetBinary = path.join(binDir, binaryName)
|
|
139
|
+
|
|
140
|
+
if (fs.existsSync(extractedBinary)) {
|
|
141
|
+
if (fs.existsSync(targetBinary)) fs.unlinkSync(targetBinary)
|
|
142
|
+
fs.copyFileSync(extractedBinary, targetBinary)
|
|
143
|
+
fs.chmodSync(targetBinary, 0o755)
|
|
144
|
+
console.log(`Installed tfcode to ${targetBinary}`)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Cleanup
|
|
148
|
+
fs.rmSync(tmpDir, { recursive: true, force: true })
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function setupBinary(sourcePath, platform) {
|
|
152
|
+
const binDir = path.join(__dirname, "bin")
|
|
153
|
+
const binaryName = platform === "windows" ? "tfcode.exe" : "tfcode"
|
|
154
|
+
const targetBinary = path.join(binDir, binaryName)
|
|
155
|
+
|
|
156
|
+
if (!fs.existsSync(binDir)) fs.mkdirSync(binDir, { recursive: true })
|
|
157
|
+
if (fs.existsSync(targetBinary)) fs.unlinkSync(targetBinary)
|
|
158
|
+
|
|
159
|
+
// Try hardlink, fall back to copy
|
|
160
|
+
try {
|
|
161
|
+
fs.linkSync(sourcePath, targetBinary)
|
|
162
|
+
} catch {
|
|
163
|
+
fs.copyFileSync(sourcePath, targetBinary)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
fs.chmodSync(targetBinary, 0o755)
|
|
167
|
+
console.log(`tfcode installed to ${targetBinary}`)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async function main() {
|
|
171
|
+
console.log("")
|
|
172
|
+
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
|
|
173
|
+
console.log(" tfcode - ToothFairyAI's official coding agent")
|
|
174
|
+
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
|
|
175
|
+
console.log("")
|
|
176
|
+
|
|
177
|
+
// Check for Python (needed for TF integration)
|
|
178
|
+
try {
|
|
179
|
+
const result = spawnSync("python3", ["--version"], { encoding: "utf8" })
|
|
180
|
+
if (result.status === 0) {
|
|
181
|
+
console.log(`✓ Found ${result.stdout.trim()}`)
|
|
182
|
+
|
|
183
|
+
// Install Python SDK
|
|
184
|
+
console.log("Installing ToothFairyAI Python SDK...")
|
|
185
|
+
const pipResult = spawnSync(
|
|
186
|
+
"python3",
|
|
187
|
+
["-m", "pip", "install", "--user", "--break-system-packages", "toothfairyai", "pydantic", "httpx", "rich"],
|
|
188
|
+
{
|
|
189
|
+
stdio: "inherit",
|
|
190
|
+
},
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
if (pipResult.status === 0) {
|
|
194
|
+
console.log("✓ Python SDK installed")
|
|
195
|
+
} else {
|
|
196
|
+
console.log("! Python SDK install failed, run manually:")
|
|
197
|
+
console.log(" pip install toothfairyai pydantic httpx rich")
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
} catch {
|
|
201
|
+
console.log("! Python 3.10+ not found. Install with:")
|
|
202
|
+
console.log(" macOS: brew install python@3.12")
|
|
203
|
+
console.log(" Ubuntu: sudo apt install python3.12")
|
|
204
|
+
console.log(" Windows: Download from python.org/downloads")
|
|
205
|
+
console.log("")
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
console.log("")
|
|
209
|
+
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
|
|
210
|
+
console.log("✓ tfcode installed successfully!")
|
|
211
|
+
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
|
|
212
|
+
console.log("")
|
|
213
|
+
console.log("Quick Start:")
|
|
214
|
+
console.log("")
|
|
215
|
+
console.log(" 1. Set credentials:")
|
|
216
|
+
console.log(' export TF_WORKSPACE_ID="your-workspace-id"')
|
|
217
|
+
console.log(' export TF_API_KEY="your-api-key"')
|
|
218
|
+
console.log("")
|
|
219
|
+
console.log(" 2. Validate:")
|
|
220
|
+
console.log(" tfcode validate")
|
|
221
|
+
console.log("")
|
|
222
|
+
console.log(" 3. Sync tools:")
|
|
223
|
+
console.log(" tfcode sync")
|
|
224
|
+
console.log("")
|
|
225
|
+
console.log(" 4. Start coding:")
|
|
226
|
+
console.log(" tfcode")
|
|
227
|
+
console.log("")
|
|
228
|
+
console.log("Documentation: https://toothfairyai.com/developers/tfcode")
|
|
229
|
+
console.log("")
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
main().catch(console.error)
|
package/README.md
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
# tfcode
|
|
2
|
-
|
|
3
|
-
**ToothFairyAI's official AI coding agent** - A terminal-based coding assistant with seamless integration to your ToothFairyAI workspace.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- 🤖 **AI-Powered Coding** - Intelligent code generation, refactoring, and debugging
|
|
8
|
-
- 🔌 **Tool Integration** - Sync and use tools from your ToothFairyAI workspace
|
|
9
|
-
- 💻 **Terminal-Based** - Fast, lightweight, runs in your terminal
|
|
10
|
-
- 🔐 **Secure** - Credentials stay in ToothFairyAI, route via TF Proxy
|
|
11
|
-
|
|
12
|
-
## Requirements
|
|
13
|
-
|
|
14
|
-
- **Python 3.10+** - Required for ToothFairyAI integration
|
|
15
|
-
- **Node.js 18+** - Required to run tfcode
|
|
16
|
-
|
|
17
|
-
## Installation
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
npm install -g @toothfairyai/tfcode@beta
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
The installer will:
|
|
24
|
-
- Check Python is installed
|
|
25
|
-
- Install the ToothFairyAI Python SDK automatically
|
|
26
|
-
|
|
27
|
-
## Quick Start
|
|
28
|
-
|
|
29
|
-
### Option A: Interactive Setup (Recommended)
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
# Run interactive setup
|
|
33
|
-
tfcode setup
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
This will guide you through entering your credentials step by step:
|
|
37
|
-
1. Enter your Workspace ID
|
|
38
|
-
2. Enter your API Key (hidden as you type)
|
|
39
|
-
3. Select your region
|
|
40
|
-
4. Validate and sync automatically
|
|
41
|
-
|
|
42
|
-
### Option B: Manual Setup
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
# 1. Set your ToothFairyAI credentials
|
|
46
|
-
export TF_WORKSPACE_ID="your-workspace-id"
|
|
47
|
-
export TF_API_KEY="your-api-key"
|
|
48
|
-
export TF_REGION="au"
|
|
49
|
-
|
|
50
|
-
# 2. Validate your credentials
|
|
51
|
-
tfcode validate
|
|
52
|
-
|
|
53
|
-
# 3. Sync tools from your workspace
|
|
54
|
-
tfcode sync
|
|
55
|
-
|
|
56
|
-
# 4. List your tools
|
|
57
|
-
tfcode tools list
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## Commands
|
|
61
|
-
|
|
62
|
-
| Command | Description |
|
|
63
|
-
|---------|-------------|
|
|
64
|
-
| `tfcode setup` | **Interactive credential setup** |
|
|
65
|
-
| `tfcode quickstart` | Show quick start guide |
|
|
66
|
-
| `tfcode validate` | Test your credentials |
|
|
67
|
-
| `tfcode sync` | Sync tools from workspace |
|
|
68
|
-
| `tfcode tools list` | List synced tools |
|
|
69
|
-
| `tfcode tools list --type api_function` | Filter by type |
|
|
70
|
-
|
|
71
|
-
## Regions
|
|
72
|
-
|
|
73
|
-
| Region | URL | Use Case |
|
|
74
|
-
|--------|-----|----------|
|
|
75
|
-
| `dev` | api.toothfairylab.link | Development/Testing |
|
|
76
|
-
| `au` | api.toothfairyai.com | Australia (Default) |
|
|
77
|
-
| `eu` | api.eu.toothfairyai.com | Europe |
|
|
78
|
-
| `us` | api.us.toothfairyai.com | United States |
|
|
79
|
-
|
|
80
|
-
## Configuration
|
|
81
|
-
|
|
82
|
-
Credentials are stored in `~/.tfcode/config.json`:
|
|
83
|
-
|
|
84
|
-
```json
|
|
85
|
-
{
|
|
86
|
-
"workspace_id": "your-workspace-id",
|
|
87
|
-
"api_key": "your-api-key",
|
|
88
|
-
"region": "au"
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
You can also set credentials via environment variables (takes priority over config file):
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
export TF_WORKSPACE_ID="your-workspace-id"
|
|
96
|
-
export TF_API_KEY="your-api-key"
|
|
97
|
-
export TF_REGION="au"
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## Getting Your Credentials
|
|
101
|
-
|
|
102
|
-
1. Log in to [ToothFairyAI](https://app.toothfairyai.com)
|
|
103
|
-
2. Go to **Settings** → **API Keys**
|
|
104
|
-
3. Copy your **Workspace ID** and **API Key**
|
|
105
|
-
|
|
106
|
-
## Troubleshooting
|
|
107
|
-
|
|
108
|
-
### "Python 3.10+ is required but not found"
|
|
109
|
-
|
|
110
|
-
Install Python:
|
|
111
|
-
- **macOS**: `brew install python@3.12`
|
|
112
|
-
- **Windows**: Download from https://python.org/downloads
|
|
113
|
-
- **Linux**: `sudo apt install python3.12`
|
|
114
|
-
|
|
115
|
-
### "Failed to validate: Invalid API key"
|
|
116
|
-
|
|
117
|
-
- Check your API key is correct
|
|
118
|
-
- Generate a new key in ToothFairyAI Settings → API Keys
|
|
119
|
-
- Run `tfcode setup` to re-enter credentials
|
|
120
|
-
|
|
121
|
-
### "Failed to validate: Connection test failed"
|
|
122
|
-
|
|
123
|
-
Try a different region:
|
|
124
|
-
- Run `tfcode setup` and select a different region
|
|
125
|
-
- Or set `TF_REGION="eu"` or `TF_REGION="us"`
|
|
126
|
-
|
|
127
|
-
### "No credentials found"
|
|
128
|
-
|
|
129
|
-
Run interactive setup:
|
|
130
|
-
```bash
|
|
131
|
-
tfcode setup
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## Documentation
|
|
135
|
-
|
|
136
|
-
- **Full Guide**: https://toothfairyai.com/developers/tfcode
|
|
137
|
-
- **API Docs**: https://apidocs.toothfairyai.com
|
|
138
|
-
- **Issues**: https://github.com/ToothFairyAI/tfcode/issues
|
|
139
|
-
|
|
140
|
-
## Credits
|
|
141
|
-
|
|
142
|
-
tfcode is based on [opencode](https://github.com/anomalyco/opencode) by [anomalyco](https://github.com/anomalyco).
|
|
143
|
-
|
|
144
|
-
## License
|
|
145
|
-
|
|
146
|
-
MIT
|
package/scripts/postinstall.cjs
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const { spawn, execSync } = require('child_process');
|
|
4
|
-
const fs = require('fs');
|
|
5
|
-
const path = require('path');
|
|
6
|
-
|
|
7
|
-
const RESET = '\x1b[0m';
|
|
8
|
-
const BOLD = '\x1b[1m';
|
|
9
|
-
const GREEN = '\x1b[32m';
|
|
10
|
-
const YELLOW = '\x1b[33m';
|
|
11
|
-
const RED = '\x1b[31m';
|
|
12
|
-
const CYAN = '\x1b[36m';
|
|
13
|
-
const DIM = '\x1b[90m';
|
|
14
|
-
|
|
15
|
-
function log(msg) {
|
|
16
|
-
console.log(msg);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function logSuccess(msg) {
|
|
20
|
-
console.log(`${GREEN}✓${RESET} ${msg}`);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function logError(msg) {
|
|
24
|
-
console.error(`${RED}✗${RESET} ${msg}`);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function logInfo(msg) {
|
|
28
|
-
console.log(`${CYAN}ℹ${RESET} ${msg}`);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function logWarning(msg) {
|
|
32
|
-
console.log(`${YELLOW}!${RESET} ${msg}`);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function checkPython() {
|
|
36
|
-
const commands = ['python3', 'python'];
|
|
37
|
-
|
|
38
|
-
for (const cmd of commands) {
|
|
39
|
-
try {
|
|
40
|
-
const result = execSync(`${cmd} --version`, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
41
|
-
const match = result.match(/Python (\d+)\.(\d+)/);
|
|
42
|
-
if (match) {
|
|
43
|
-
const major = parseInt(match[1]);
|
|
44
|
-
const minor = parseInt(match[2]);
|
|
45
|
-
if (major >= 3 && minor >= 10) {
|
|
46
|
-
return { cmd, version: result.trim() };
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
} catch {}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function installPythonDeps(pythonCmd) {
|
|
56
|
-
return new Promise((resolve, reject) => {
|
|
57
|
-
const packages = ['toothfairyai', 'pydantic', 'httpx', 'rich'];
|
|
58
|
-
|
|
59
|
-
log(`${DIM}Installing Python packages: ${packages.join(', ')}...${RESET}`);
|
|
60
|
-
|
|
61
|
-
// Try with --user first, then --break-system-packages if needed
|
|
62
|
-
const args = ['-m', 'pip', 'install', '--user', ...packages];
|
|
63
|
-
|
|
64
|
-
const proc = spawn(pythonCmd, args, {
|
|
65
|
-
stdio: 'inherit',
|
|
66
|
-
shell: process.platform === 'win32'
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
proc.on('close', (code) => {
|
|
70
|
-
if (code === 0) {
|
|
71
|
-
resolve();
|
|
72
|
-
} else {
|
|
73
|
-
// Try with --break-system-packages flag
|
|
74
|
-
log(`${DIM}Retrying with --break-system-packages...${RESET}`);
|
|
75
|
-
const retryArgs = ['-m', 'pip', 'install', '--user', '--break-system-packages', ...packages];
|
|
76
|
-
const retry = spawn(pythonCmd, retryArgs, {
|
|
77
|
-
stdio: 'inherit',
|
|
78
|
-
shell: process.platform === 'win32'
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
retry.on('close', (retryCode) => {
|
|
82
|
-
if (retryCode === 0) {
|
|
83
|
-
resolve();
|
|
84
|
-
} else {
|
|
85
|
-
reject(new Error(`pip install exited with code ${retryCode}`));
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
retry.on('error', (err) => {
|
|
90
|
-
reject(err);
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
proc.on('error', (err) => {
|
|
96
|
-
reject(err);
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async function main() {
|
|
102
|
-
log('');
|
|
103
|
-
log(`${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
|
|
104
|
-
log(`${BOLD} tfcode - ToothFairyAI's official coding agent${RESET}`);
|
|
105
|
-
log(`${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
|
|
106
|
-
log('');
|
|
107
|
-
|
|
108
|
-
// Check for Python
|
|
109
|
-
logInfo('Checking Python installation...');
|
|
110
|
-
const python = checkPython();
|
|
111
|
-
|
|
112
|
-
if (!python) {
|
|
113
|
-
log('');
|
|
114
|
-
logError('Python 3.10+ is required but not found.');
|
|
115
|
-
log('');
|
|
116
|
-
log(`${BOLD}Please install Python 3.10 or later:${RESET}`);
|
|
117
|
-
log('');
|
|
118
|
-
log(` ${CYAN}macOS:${RESET} brew install python@3.12`);
|
|
119
|
-
log(` ${CYAN}Ubuntu:${RESET} sudo apt-get install python3.12`);
|
|
120
|
-
log(` ${CYAN}Windows:${RESET} Download from https://python.org/downloads`);
|
|
121
|
-
log('');
|
|
122
|
-
log(`${DIM}After installing Python, run: npm rebuild tfcode${RESET}`);
|
|
123
|
-
log('');
|
|
124
|
-
process.exit(1);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
logSuccess(`Found ${python.version} (${python.cmd})`);
|
|
128
|
-
log('');
|
|
129
|
-
|
|
130
|
-
// Install Python dependencies
|
|
131
|
-
logInfo('Installing ToothFairyAI Python SDK...');
|
|
132
|
-
try {
|
|
133
|
-
await installPythonDeps(python.cmd);
|
|
134
|
-
logSuccess('Python dependencies installed');
|
|
135
|
-
} catch (err) {
|
|
136
|
-
logWarning(`Failed to install Python dependencies: ${err.message}`);
|
|
137
|
-
log('');
|
|
138
|
-
log(`${DIM}You can install them manually with:${RESET}`);
|
|
139
|
-
log(` ${CYAN}${python.cmd} -m pip install toothfairyai pydantic httpx rich${RESET}`);
|
|
140
|
-
log('');
|
|
141
|
-
// Don't exit - user might install manually later
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
log('');
|
|
145
|
-
log(`${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
|
|
146
|
-
log(`${GREEN}✓ tfcode installed successfully!${RESET}`);
|
|
147
|
-
log(`${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
|
|
148
|
-
log('');
|
|
149
|
-
log(`${BOLD}Quick Start:${RESET}`);
|
|
150
|
-
log('');
|
|
151
|
-
log(` ${CYAN}1.${RESET} Set your ToothFairyAI credentials:`);
|
|
152
|
-
log(` ${DIM}export TF_WORKSPACE_ID="your-workspace-id"${RESET}`);
|
|
153
|
-
log(` ${DIM}export TF_API_KEY="your-api-key"${RESET}`);
|
|
154
|
-
log('');
|
|
155
|
-
log(` ${CYAN}2.${RESET} Validate your credentials:`);
|
|
156
|
-
log(` ${DIM}tfcode validate${RESET}`);
|
|
157
|
-
log('');
|
|
158
|
-
log(` ${CYAN}3.${RESET} Sync tools from your workspace:`);
|
|
159
|
-
log(` ${DIM}tfcode sync${RESET}`);
|
|
160
|
-
log('');
|
|
161
|
-
log(` ${CYAN}4.${RESET} Start coding:`);
|
|
162
|
-
log(` ${DIM}tfcode${RESET}`);
|
|
163
|
-
log('');
|
|
164
|
-
log(`${DIM}Documentation: https://toothfairyai.com/developers/tfcode${RESET}`);
|
|
165
|
-
log('');
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
main().catch((err) => {
|
|
169
|
-
logError(`Installation failed: ${err.message}`);
|
|
170
|
-
process.exit(1);
|
|
171
|
-
});
|
package/scripts/quickstart.cjs
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
console.log(`
|
|
4
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
5
|
-
tfcode - Quick Start Guide
|
|
6
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
7
|
-
|
|
8
|
-
Welcome to tfcode! Follow these steps to get started:
|
|
9
|
-
|
|
10
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
11
|
-
│ STEP 1: Set Your Credentials │
|
|
12
|
-
├─────────────────────────────────────────────────────────────┤
|
|
13
|
-
│ │
|
|
14
|
-
│ export TF_WORKSPACE_ID="your-workspace-id" │
|
|
15
|
-
│ export TF_API_KEY="your-api-key" │
|
|
16
|
-
│ export TF_REGION="au" │
|
|
17
|
-
│ │
|
|
18
|
-
│ Regions: au (Australia), eu (Europe), us (United States) │
|
|
19
|
-
│ │
|
|
20
|
-
└─────────────────────────────────────────────────────────────┘
|
|
21
|
-
|
|
22
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
23
|
-
│ STEP 2: Validate Connection │
|
|
24
|
-
├─────────────────────────────────────────────────────────────┤
|
|
25
|
-
│ │
|
|
26
|
-
│ tfcode validate │
|
|
27
|
-
│ │
|
|
28
|
-
│ This checks your credentials are correct. │
|
|
29
|
-
│ │
|
|
30
|
-
└─────────────────────────────────────────────────────────────┘
|
|
31
|
-
|
|
32
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
33
|
-
│ STEP 3: Sync Your Tools │
|
|
34
|
-
├─────────────────────────────────────────────────────────────┤
|
|
35
|
-
│ │
|
|
36
|
-
│ tfcode sync │
|
|
37
|
-
│ │
|
|
38
|
-
│ This downloads your tools from ToothFairyAI. │
|
|
39
|
-
│ │
|
|
40
|
-
└─────────────────────────────────────────────────────────────┘
|
|
41
|
-
|
|
42
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
43
|
-
│ STEP 4: Start Coding! │
|
|
44
|
-
├─────────────────────────────────────────────────────────────┤
|
|
45
|
-
│ │
|
|
46
|
-
│ tfcode │
|
|
47
|
-
│ │
|
|
48
|
-
│ Start the AI coding assistant. │
|
|
49
|
-
│ │
|
|
50
|
-
└─────────────────────────────────────────────────────────────┘
|
|
51
|
-
|
|
52
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
53
|
-
|
|
54
|
-
Useful Commands:
|
|
55
|
-
|
|
56
|
-
tfcode validate Test your credentials
|
|
57
|
-
tfcode sync Sync tools from workspace
|
|
58
|
-
tfcode tools list Show all your tools
|
|
59
|
-
tfcode Start coding assistant
|
|
60
|
-
|
|
61
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
62
|
-
|
|
63
|
-
Need help? https://toothfairyai.com/developers/tfcode
|
|
64
|
-
|
|
65
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
66
|
-
`);
|