xyteeecode 1.0.4 → 1.0.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.
@@ -8,38 +8,72 @@ const os = require("os")
8
8
  const forwardedSignals = ["SIGINT", "SIGTERM", "SIGHUP"]
9
9
 
10
10
  function run(target) {
11
- const child = childProcess.spawn(target, process.argv.slice(2), {
12
- stdio: "inherit",
13
- })
11
+ return new Promise((resolve) => {
12
+ const localLibDir = path.dirname(target)
13
+ // The candidate path looks like ".../xyteeecode-linux-arm64-musl/bin/xyteeecode".
14
+ const isMusl = /-musl[/\\]/.test(target)
15
+ const env = { ...process.env }
16
+ if (isMusl) {
17
+ // The musl builds are dynamically linked against libc/libstdc++.
18
+ // Termux (bionic) and bare Alpine installs have no libstdc++ in the
19
+ // default library search path, so point the loader at the sibling libs
20
+ // bundled inside the platform package.
21
+ env.LD_LIBRARY_PATH = env.LD_LIBRARY_PATH
22
+ ? localLibDir + path.delimiter + env.LD_LIBRARY_PATH
23
+ : localLibDir
24
+ }
14
25
 
15
- child.on("error", (error) => {
16
- console.error(error.message)
17
- process.exit(1)
18
- })
26
+ const child = childProcess.spawn(target, process.argv.slice(2), {
27
+ stdio: "inherit",
28
+ env,
29
+ })
19
30
 
20
- const forwarders = {}
21
- for (const signal of forwardedSignals) {
22
- forwarders[signal] = () => {
23
- try {
24
- child.kill(signal)
25
- } catch {
26
- // The child may have already exited.
31
+ let spawned = false
32
+ let exited = false
33
+
34
+ child.on("error", (error) => {
35
+ // exec/execvp can't find the interpreter or the executable itself
36
+ // (e.g. a glibc binary on Termux's bionic libc). Allow the caller to
37
+ // fall back to the next candidate (e.g. the musl build with its bundled
38
+ // loader and libraries for Termux).
39
+ if (error.code === "ENOENT" && !spawned && !exited) {
40
+ resolve(false)
41
+ return
27
42
  }
28
- }
29
- process.on(signal, forwarders[signal])
30
- }
43
+ console.error(error.message)
44
+ process.exit(1)
45
+ })
31
46
 
32
- child.on("exit", (code, signal) => {
33
- for (const forwardedSignal of forwardedSignals) {
34
- process.removeListener(forwardedSignal, forwarders[forwardedSignal])
35
- }
47
+ child.on("spawn", () => {
48
+ spawned = true
49
+ resolve(true)
50
+ })
36
51
 
37
- if (signal) {
38
- process.kill(process.pid, signal)
39
- return
52
+ const forwarders = {}
53
+ for (const signal of forwardedSignals) {
54
+ forwarders[signal] = () => {
55
+ try {
56
+ child.kill(signal)
57
+ } catch {
58
+ // The child may have already exited.
59
+ }
60
+ }
61
+ process.on(signal, forwarders[signal])
40
62
  }
41
63
 
42
- process.exit(typeof code === "number" ? code : 0)
64
+ child.on("exit", (code, signal) => {
65
+ exited = true
66
+ for (const forwardedSignal of forwardedSignals) {
67
+ process.removeListener(forwardedSignal, forwarders[forwardedSignal])
68
+ }
69
+
70
+ if (signal) {
71
+ process.kill(process.pid, signal)
72
+ return
73
+ }
74
+
75
+ process.exit(typeof code === "number" ? code : 0)
76
+ })
43
77
  })
44
78
  }
45
79
 
@@ -49,7 +83,7 @@ const scriptPath = fs.realpathSync(__filename)
49
83
  const scriptDir = path.dirname(scriptPath)
50
84
 
51
85
  //
52
- const cached = path.join(scriptDir, ".opencode")
86
+ const cached = path.join(scriptDir, ".xyteeecode")
53
87
 
54
88
  const platformMap = {
55
89
  darwin: "darwin",
@@ -71,7 +105,7 @@ if (!arch) {
71
105
  arch = os.arch()
72
106
  }
73
107
  const base = "xyteeecode-" + platform + "-" + arch
74
- const binary = platform === "windows" ? "opencode.exe" : "opencode"
108
+ const binary = platform === "windows" ? "xyteeecode.exe" : "xyteeecode"
75
109
 
76
110
  function supportsAvx2() {
77
111
  if (arch !== "x64") return false
@@ -123,28 +157,40 @@ function supportsAvx2() {
123
157
  return false
124
158
  }
125
159
 
160
+ function isTermux() {
161
+ return Boolean(
162
+ process.env.TERMUX_VERSION ||
163
+ (process.env.PREFIX && process.env.PREFIX.includes("com.termux")),
164
+ )
165
+ }
166
+
126
167
  const names = (() => {
127
168
  const avx2 = supportsAvx2()
128
169
  const baseline = arch === "x64" && !avx2
129
170
 
130
171
  if (platform === "linux") {
131
- const musl = (() => {
132
- try {
133
- if (fs.existsSync("/etc/alpine-release")) return true
134
- } catch {
135
- // ignore
136
- }
172
+ // Stock Termux uses Android's bionic libc, so a glibc-linked build cannot
173
+ // start. Prefer the musl build there (its bundled loader and libraries are
174
+ // wired up during package postinstall).
175
+ const musl =
176
+ isTermux() ||
177
+ (() => {
178
+ try {
179
+ if (fs.existsSync("/etc/alpine-release")) return true
180
+ } catch {
181
+ // ignore
182
+ }
137
183
 
138
- try {
139
- const result = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" })
140
- const text = ((result.stdout || "") + (result.stderr || "")).toLowerCase()
141
- if (text.includes("musl")) return true
142
- } catch {
143
- // ignore
144
- }
184
+ try {
185
+ const result = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" })
186
+ const text = ((result.stdout || "") + (result.stderr || "")).toLowerCase()
187
+ if (text.includes("musl")) return true
188
+ } catch {
189
+ // ignore
190
+ }
145
191
 
146
- return false
147
- })()
192
+ return false
193
+ })()
148
194
 
149
195
  if (musl) {
150
196
  if (arch === "x64") {
@@ -168,26 +214,43 @@ const names = (() => {
168
214
  return [base]
169
215
  })()
170
216
 
171
- function findBinary(startDir) {
217
+ function findBinaries(startDir) {
172
218
  let current = startDir
173
219
  for (;;) {
174
220
  const modules = path.join(current, "node_modules")
175
221
  if (fs.existsSync(modules)) {
222
+ const found = []
176
223
  for (const name of names) {
177
224
  const candidate = path.join(modules, name, "bin", binary)
178
- if (fs.existsSync(candidate)) return candidate
225
+ if (fs.existsSync(candidate)) found.push(candidate)
179
226
  }
227
+ if (found.length) return found
180
228
  }
181
229
  const parent = path.dirname(current)
182
230
  if (parent === current) {
183
- return
231
+ return []
184
232
  }
185
233
  current = parent
186
234
  }
187
235
  }
188
236
 
189
- const resolved = envPath || (fs.existsSync(cached) ? cached : findBinary(scriptDir))
190
- if (!resolved) {
237
+ async function main() {
238
+ const candidates = []
239
+ if (envPath) {
240
+ candidates.push(envPath)
241
+ } else {
242
+ if (fs.existsSync(cached)) candidates.push(cached)
243
+ candidates.push(...findBinaries(scriptDir))
244
+ }
245
+
246
+ const seen = new Set()
247
+ for (const candidate of candidates) {
248
+ if (seen.has(candidate)) continue
249
+ seen.add(candidate)
250
+ const ok = await run(candidate)
251
+ if (ok) return
252
+ }
253
+
191
254
  console.error(
192
255
  "It seems that your package manager failed to install the right version of the xyteeecode CLI for your platform. You can try manually installing " +
193
256
  names.map((n) => `\"${n}\"`).join(" or ") +
@@ -196,4 +259,4 @@ if (!resolved) {
196
259
  process.exit(1)
197
260
  }
198
261
 
199
- run(resolved)
262
+ main()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xyteeecode",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "xyteeecode - AI coding agent CLI",
5
5
  "license": "MIT",
6
6
  "homepage": "https://xyteee.com",
@@ -18,13 +18,15 @@
18
18
  "README.md"
19
19
  ],
20
20
  "bin": {
21
- "xyteeecode": "bin/opencode"
21
+ "xyteeecode": "bin/xyteeecode"
22
22
  },
23
23
  "engines": {
24
24
  "node": ">=18"
25
25
  },
26
26
  "optionalDependencies": {
27
- "xyteeecode-linux-arm64": "1.0.4",
28
- "xyteeecode-linux-x64": "1.0.4"
27
+ "xyteeecode-linux-arm64": "1.0.6",
28
+ "xyteeecode-linux-x64": "1.0.6",
29
+ "xyteeecode-linux-arm64-musl": "1.0.6",
30
+ "xyteeecode-linux-x64-musl": "1.0.6"
29
31
  }
30
32
  }