goatchain-cli 0.0.73-beta.4 → 0.0.73-beta.6
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/bin/dim.mjs +133 -3
- package/package.json +6 -6
package/bin/dim.mjs
CHANGED
|
@@ -38,9 +38,12 @@ const wrapperPm
|
|
|
38
38
|
|
|
39
39
|
const args = process.argv.slice(2)
|
|
40
40
|
const forwardArgs = args[0] === 'opentui' ? args.slice(1) : args
|
|
41
|
-
runOpentui(forwardArgs)
|
|
41
|
+
runOpentui(forwardArgs).catch((err) => {
|
|
42
|
+
console.error('[dim] Unexpected error: ' + (err && err.stack ? err.stack : err))
|
|
43
|
+
process.exit(1)
|
|
44
|
+
})
|
|
42
45
|
|
|
43
|
-
function runOpentui(restArgs) {
|
|
46
|
+
async function runOpentui(restArgs) {
|
|
44
47
|
const envPath = process.env.DIMCODE_BIN_PATH
|
|
45
48
|
if (envPath) {
|
|
46
49
|
if (!fs.existsSync(envPath)) {
|
|
@@ -70,7 +73,12 @@ function runOpentui(restArgs) {
|
|
|
70
73
|
console.error('[dim] Script dir: ' + scriptDir)
|
|
71
74
|
}
|
|
72
75
|
|
|
73
|
-
|
|
76
|
+
let resolved = findBinary(scriptDir, base, binary)
|
|
77
|
+
|
|
78
|
+
if (!resolved) {
|
|
79
|
+
resolved = await ensureCachedBinary(base, binary, wrapperVersion)
|
|
80
|
+
}
|
|
81
|
+
|
|
74
82
|
if (!resolved) {
|
|
75
83
|
console.error(
|
|
76
84
|
'[dim] Could not find the opentui binary for your platform.\n'
|
|
@@ -92,6 +100,128 @@ function runOpentui(restArgs) {
|
|
|
92
100
|
spawnBinary(resolved, restArgs)
|
|
93
101
|
}
|
|
94
102
|
|
|
103
|
+
async function ensureCachedBinary(base, binary, version) {
|
|
104
|
+
if (!version) {
|
|
105
|
+
if (process.env.DIMCODE_DEBUG)
|
|
106
|
+
console.error('[dim] No wrapper version available; skipping registry fallback')
|
|
107
|
+
return null
|
|
108
|
+
}
|
|
109
|
+
if (process.env.DIMCODE_NO_DOWNLOAD === '1') {
|
|
110
|
+
if (process.env.DIMCODE_DEBUG)
|
|
111
|
+
console.error('[dim] DIMCODE_NO_DOWNLOAD=1; skipping registry fallback')
|
|
112
|
+
return null
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const home = os.homedir()
|
|
116
|
+
const cacheDir = path.join(home, '.dimcode', 'binaries', base, version)
|
|
117
|
+
const cachedBin = path.join(cacheDir, 'bin', binary)
|
|
118
|
+
if (fs.existsSync(cachedBin)) {
|
|
119
|
+
if (process.env.DIMCODE_DEBUG)
|
|
120
|
+
console.error('[dim] Using cached binary: ' + cachedBin)
|
|
121
|
+
return cachedBin
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (typeof fetch !== 'function') {
|
|
125
|
+
console.error('[dim] Registry fallback requires Node 18+ (global fetch). Please reinstall after upgrading Node.')
|
|
126
|
+
return null
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const registry = (process.env.DIMCODE_REGISTRY || 'https://registry.npmjs.org').replace(/\/+$/, '')
|
|
130
|
+
const url = registry + '/' + base + '/-/' + base + '-' + version + '.tgz'
|
|
131
|
+
|
|
132
|
+
console.error('[dim] Platform binary missing locally. Fetching ' + base + '@' + version + '...')
|
|
133
|
+
if (process.env.DIMCODE_DEBUG)
|
|
134
|
+
console.error('[dim] URL: ' + url)
|
|
135
|
+
|
|
136
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'dimcode-dl-'))
|
|
137
|
+
const tgzPath = path.join(tmpDir, 'pkg.tgz')
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
await downloadFile(url, tgzPath)
|
|
141
|
+
fs.mkdirSync(cacheDir, { recursive: true })
|
|
142
|
+
extractTarball(tgzPath, cacheDir)
|
|
143
|
+
if (!isWindows && fs.existsSync(cachedBin)) {
|
|
144
|
+
try { fs.chmodSync(cachedBin, 0o755) }
|
|
145
|
+
catch {}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
console.error('[dim] Failed to fetch platform binary: ' + (err && err.message ? err.message : err))
|
|
150
|
+
console.error('[dim] You can retry, set DIMCODE_BIN_PATH to a local binary, or reinstall with:')
|
|
151
|
+
console.error(' npm uninstall -g ' + wrapperName + ' && npm install -g ' + wrapperName + '@beta')
|
|
152
|
+
return null
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
try { fs.rmSync(tmpDir, { recursive: true, force: true }) }
|
|
156
|
+
catch {}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (!fs.existsSync(cachedBin)) {
|
|
160
|
+
console.error('[dim] Downloaded archive did not contain expected binary at ' + cachedBin)
|
|
161
|
+
return null
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
console.error('[dim] Cached at ' + cachedBin)
|
|
165
|
+
return cachedBin
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function downloadFile(url, dest) {
|
|
169
|
+
let currentUrl = url
|
|
170
|
+
for (let hop = 0; hop < 5; hop++) {
|
|
171
|
+
const res = await fetch(currentUrl, { redirect: 'manual' })
|
|
172
|
+
if (res.status >= 300 && res.status < 400 && res.headers.get('location')) {
|
|
173
|
+
currentUrl = new URL(res.headers.get('location'), currentUrl).toString()
|
|
174
|
+
continue
|
|
175
|
+
}
|
|
176
|
+
if (!res.ok)
|
|
177
|
+
throw new Error('HTTP ' + res.status + ' ' + res.statusText + ' for ' + currentUrl)
|
|
178
|
+
|
|
179
|
+
const total = Number(res.headers.get('content-length') || 0)
|
|
180
|
+
const out = fs.createWriteStream(dest)
|
|
181
|
+
let downloaded = 0
|
|
182
|
+
let lastShown = -1
|
|
183
|
+
const reader = res.body.getReader()
|
|
184
|
+
for (;;) {
|
|
185
|
+
const { done, value } = await reader.read()
|
|
186
|
+
if (done) break
|
|
187
|
+
out.write(Buffer.from(value))
|
|
188
|
+
downloaded += value.length
|
|
189
|
+
if (total && process.stderr.isTTY) {
|
|
190
|
+
const pct = Math.floor((downloaded / total) * 100)
|
|
191
|
+
if (pct !== lastShown && pct % 5 === 0) {
|
|
192
|
+
process.stderr.write('\r[dim] Downloading... ' + pct + '%')
|
|
193
|
+
lastShown = pct
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
out.end()
|
|
198
|
+
await new Promise((resolve, reject) => {
|
|
199
|
+
out.on('close', resolve)
|
|
200
|
+
out.on('error', reject)
|
|
201
|
+
})
|
|
202
|
+
if (process.stderr.isTTY)
|
|
203
|
+
process.stderr.write('\r[dim] Downloaded ' + (downloaded / 1024 / 1024).toFixed(1) + ' MB \n')
|
|
204
|
+
else
|
|
205
|
+
console.error('[dim] Downloaded ' + (downloaded / 1024 / 1024).toFixed(1) + ' MB')
|
|
206
|
+
return
|
|
207
|
+
}
|
|
208
|
+
throw new Error('Too many redirects')
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function extractTarball(tgzPath, destDir) {
|
|
212
|
+
const result = childProcess.spawnSync(
|
|
213
|
+
'tar',
|
|
214
|
+
['-xzf', tgzPath, '-C', destDir, '--strip-components=1'],
|
|
215
|
+
{ stdio: process.env.DIMCODE_DEBUG ? 'inherit' : 'pipe' },
|
|
216
|
+
)
|
|
217
|
+
if (result.error)
|
|
218
|
+
throw new Error('tar not available: ' + result.error.message)
|
|
219
|
+
if (result.status !== 0) {
|
|
220
|
+
const stderr = result.stderr ? result.stderr.toString() : ''
|
|
221
|
+
throw new Error('tar exited with status ' + result.status + (stderr ? ': ' + stderr.trim() : ''))
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
95
225
|
function findBinary(startDir, base, binary) {
|
|
96
226
|
let current = startDir
|
|
97
227
|
for (;;) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "goatchain-cli",
|
|
3
|
-
"version": "0.0.73-beta.
|
|
3
|
+
"version": "0.0.73-beta.6",
|
|
4
4
|
"description": "AI coding agent CLI and terminal coding assistant with an interactive TUI (beta channel)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
"bin"
|
|
12
12
|
],
|
|
13
13
|
"optionalDependencies": {
|
|
14
|
-
"goatchain-cli-darwin-arm64": "0.0.73-beta.
|
|
15
|
-
"goatchain-cli-darwin-x64": "0.0.73-beta.
|
|
16
|
-
"goatchain-cli-linux-arm64": "0.0.73-beta.
|
|
17
|
-
"goatchain-cli-linux-x64": "0.0.73-beta.
|
|
18
|
-
"goatchain-cli-windows-x64": "0.0.73-beta.
|
|
14
|
+
"goatchain-cli-darwin-arm64": "0.0.73-beta.6",
|
|
15
|
+
"goatchain-cli-darwin-x64": "0.0.73-beta.6",
|
|
16
|
+
"goatchain-cli-linux-arm64": "0.0.73-beta.6",
|
|
17
|
+
"goatchain-cli-linux-x64": "0.0.73-beta.6",
|
|
18
|
+
"goatchain-cli-windows-x64": "0.0.73-beta.6"
|
|
19
19
|
}
|
|
20
20
|
}
|