dimcode 0.0.67-beta.9 → 0.0.67

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.
Files changed (2) hide show
  1. package/bin/dim.mjs +150 -9
  2. package/package.json +6 -6
package/bin/dim.mjs CHANGED
@@ -11,14 +11,25 @@ const __dirname = path.dirname(__filename)
11
11
  const isWindows = os.platform() === 'win32'
12
12
 
13
13
  let wrapperVersion = ''
14
+ let wrapperName = 'dimcode'
14
15
  try {
15
16
  const pkg = JSON.parse(
16
17
  fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'),
17
18
  )
18
19
  wrapperVersion = pkg.version || ''
20
+ if (pkg.name)
21
+ wrapperName = pkg.name
19
22
  }
20
23
  catch {}
21
24
 
25
+ // Inner binary file name shipped inside each platform sub-package's bin/.
26
+ // dimcode → bin/dimcode(.exe); goatchain-cli → bin/goatchain(.exe).
27
+ const BINARY_BASENAMES = {
28
+ 'dimcode': 'dimcode',
29
+ 'goatchain-cli': 'goatchain',
30
+ }
31
+ const binaryBasename = BINARY_BASENAMES[wrapperName] || wrapperName
32
+
22
33
  const wrapperDir = path.join(__dirname, '..').replace(/\\/g, '/').toLowerCase()
23
34
  const wrapperPm
24
35
  = wrapperDir.includes('.bun/') || wrapperDir.includes('bun/install/')
@@ -27,9 +38,12 @@ const wrapperPm
27
38
 
28
39
  const args = process.argv.slice(2)
29
40
  const forwardArgs = args[0] === 'opentui' ? args.slice(1) : args
30
- runOpentui(forwardArgs)
41
+ runOpentui(forwardArgs).catch((err) => {
42
+ console.error('[dim] Unexpected error: ' + (err && err.stack ? err.stack : err))
43
+ process.exit(1)
44
+ })
31
45
 
32
- function runOpentui(restArgs) {
46
+ async function runOpentui(restArgs) {
33
47
  const envPath = process.env.DIMCODE_BIN_PATH
34
48
  if (envPath) {
35
49
  if (!fs.existsSync(envPath)) {
@@ -49,17 +63,22 @@ function runOpentui(restArgs) {
49
63
  const archMap = { x64: 'x64', arm64: 'arm64' }
50
64
  const platform = platformMap[os.platform()] || os.platform()
51
65
  const arch = archMap[os.arch()] || os.arch()
52
- const base = 'dimcode-' + platform + '-' + arch
53
- const binary = platform === 'windows' ? 'dimcode.exe' : 'dimcode'
66
+ const base = wrapperName + '-' + platform + '-' + arch
67
+ const binary = platform === 'windows' ? binaryBasename + '.exe' : binaryBasename
54
68
 
55
69
  if (process.env.DIMCODE_DEBUG) {
56
- console.error('[dim] Wrapper version: ' + wrapperVersion)
70
+ console.error('[dim] Wrapper: ' + wrapperName + '@' + wrapperVersion)
57
71
  console.error('[dim] Platform: ' + platform + ' Arch: ' + arch)
58
72
  console.error('[dim] Looking for package: ' + base)
59
73
  console.error('[dim] Script dir: ' + scriptDir)
60
74
  }
61
75
 
62
- const resolved = findBinary(scriptDir, base, binary)
76
+ let resolved = findBinary(scriptDir, base, binary)
77
+
78
+ if (!resolved) {
79
+ resolved = await ensureCachedBinary(base, binary, wrapperVersion)
80
+ }
81
+
63
82
  if (!resolved) {
64
83
  console.error(
65
84
  '[dim] Could not find the opentui binary for your platform.\n'
@@ -70,7 +89,7 @@ function runOpentui(restArgs) {
70
89
  + ' Searched: ' + scriptDir + ' (and parent directories)\n'
71
90
  + '\n'
72
91
  + 'Try uninstalling and reinstalling the beta channel:\n'
73
- + ' npm uninstall -g dimcode && npm install -g dimcode@beta\n',
92
+ + ' npm uninstall -g ' + wrapperName + ' && npm install -g ' + wrapperName + '@beta\n',
74
93
  )
75
94
  process.exit(1)
76
95
  }
@@ -81,6 +100,128 @@ function runOpentui(restArgs) {
81
100
  spawnBinary(resolved, restArgs)
82
101
  }
83
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
+
84
225
  function findBinary(startDir, base, binary) {
85
226
  let current = startDir
86
227
  for (;;) {
@@ -100,7 +241,7 @@ function findBinary(startDir, base, binary) {
100
241
  function spawnBinary(target, forwardedArgs) {
101
242
  const env = {
102
243
  ...process.env,
103
- DIMCODE_NPM_PACKAGE: 'dimcode',
244
+ DIMCODE_NPM_PACKAGE: wrapperName,
104
245
  DIMCODE_NPM_PACKAGE_MANAGER: wrapperPm,
105
246
  DIMCODE_NPM_PACKAGE_ROOT: path.resolve(__dirname, '..'),
106
247
  }
@@ -124,7 +265,7 @@ function spawnBinary(target, forwardedArgs) {
124
265
  '[dim] The binary file was not found. Try reinstalling:',
125
266
  )
126
267
  console.error(
127
- ' npm uninstall -g dimcode && npm install -g dimcode@beta',
268
+ ' npm uninstall -g ' + wrapperName + ' && npm install -g ' + wrapperName + '@beta',
128
269
  )
129
270
  }
130
271
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dimcode",
3
- "version": "0.0.67-beta.9",
3
+ "version": "0.0.67",
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
- "dimcode-darwin-arm64": "0.0.67-beta.9",
15
- "dimcode-darwin-x64": "0.0.67-beta.9",
16
- "dimcode-linux-arm64": "0.0.67-beta.9",
17
- "dimcode-linux-x64": "0.0.67-beta.9",
18
- "dimcode-windows-x64": "0.0.67-beta.9"
14
+ "dimcode-darwin-arm64": "0.0.67",
15
+ "dimcode-darwin-x64": "0.0.67",
16
+ "dimcode-linux-arm64": "0.0.67",
17
+ "dimcode-linux-x64": "0.0.67",
18
+ "dimcode-windows-x64": "0.0.67"
19
19
  }
20
20
  }