xyteeecode 1.0.7 → 1.0.9

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/README.md CHANGED
@@ -67,6 +67,47 @@ xyteeecode run "explain this codebase" --model kira/qwen3.8-flash-free
67
67
 
68
68
  Authenticate with any provider the CLI supports (Anthropic, OpenAI, Groq, and hundreds more via models.dev), either through the built-in `/login` flow or by adding provider config the same way as above.
69
69
 
70
+ ### With Connect (AgentRouter)
71
+
72
+ [AgentRouter](https://agentrouter.org) is a free AI coding gateway with OpenAI-compatible and Anthropic-compatible endpoints. Add one or both gateways to your global config:
73
+
74
+ `~/.config/opencode/opencode.jsonc`
75
+
76
+ ```jsonc
77
+ {
78
+ "provider": {
79
+ "connect": {
80
+ "npm": "@ai-sdk/openai-compatible",
81
+ "name": "Connect (OpenAI gateway)",
82
+ "options": {
83
+ "baseURL": "https://agentrouter.org/v1",
84
+ "apiKey": "{env:AGENTROUTER_API_KEY}"
85
+ },
86
+ "models": {
87
+ "deepseek-v4-flash": { "name": "DeepSeek V4 Flash" },
88
+ "glm-5.3": { "name": "GLM 5.3" },
89
+ "gpt-5.6-sol": { "name": "GPT 5.6 SOL" }
90
+ }
91
+ },
92
+ "connect-anthropic": {
93
+ "npm": "@ai-sdk/anthropic",
94
+ "name": "Connect (Anthropic gateway)",
95
+ "options": {
96
+ "baseURL": "https://agentrouter.org",
97
+ "apiKey": "{env:AGENTROUTER_API_KEY}"
98
+ },
99
+ "models": {
100
+ "claude-opus-5": { "name": "Claude Opus 5" },
101
+ "claude-opus-4-8": { "name": "Claude Opus 4-8" }
102
+ }
103
+ }
104
+ },
105
+ "model": "connect/deepseek-v4-flash"
106
+ }
107
+ ```
108
+
109
+ Note: for the Anthropic gateway the base URL must **not** include `/v1`. The model list is dynamic — always check the latest models at [https://ps.air-outer.com/console/personal](https://ps.air-outer.com/console/personal).
110
+
70
111
  ## Commands
71
112
 
72
113
  - `xyteeecode` — launch the interactive terminal UI
package/bin/xyteeecode CHANGED
@@ -7,27 +7,73 @@ const os = require("os")
7
7
 
8
8
  const forwardedSignals = ["SIGINT", "SIGTERM", "SIGHUP"]
9
9
 
10
- function run(target) {
10
+ // Loader fatal-message patterns. When the bundled musl loader cannot start
11
+ // the target it prints one of these and exits non-zero before the program
12
+ // does anything; in that case we retry the same binary through its PT_INTERP.
13
+ const loaderFatal =
14
+ /Not a valid dynamic program|Error loading shared library|Error relocating .*/i
15
+
16
+ function run(target, inheritedEnv, bypassLoader) {
11
17
  return new Promise((resolve) => {
12
- const localLibDir = path.dirname(target)
18
+ const binDir = path.dirname(target)
13
19
  // The candidate path looks like ".../xyteeecode-linux-arm64-musl/bin/xyteeecode".
14
20
  const isMusl = /-musl[/\\]/.test(target)
15
- const env = { ...process.env }
21
+ const env = { ...(inheritedEnv ?? process.env) }
22
+
16
23
  if (isMusl) {
17
24
  // The musl builds are dynamically linked against libc/libstdc++.
18
25
  // Termux (bionic) and bare Alpine installs have no libstdc++ in the
19
26
  // default library search path, so point the loader at the sibling libs
20
27
  // bundled inside the platform package.
21
28
  env.LD_LIBRARY_PATH = env.LD_LIBRARY_PATH
22
- ? localLibDir + path.delimiter + env.LD_LIBRARY_PATH
23
- : localLibDir
29
+ ? binDir + path.delimiter + env.LD_LIBRARY_PATH
30
+ : binDir
31
+ }
32
+
33
+ // Stock Termux injects libtermux-exec-ld-preload.so through LD_PRELOAD,
34
+ // which the bundled musl loader cannot load. Only on Termux/Android/arm64
35
+ // with the musl build, drop the preload variables (this touches the child
36
+ // environment only, never the user's shell) and start the binary via the
37
+ // bundled loader explicitly. An explicit loader invocation avoids relying
38
+ // on bionic's exec for the musl PT_INTERP.
39
+ //
40
+ // process.platform/arch mirror os.platform()/os.arch(); both are checked so
41
+ // the launcher stays scriptable (os is monkeypatchable in node, process
42
+ // fields are monkeypatchable in bundlers like bun).
43
+ const loader = isMusl ? path.join(binDir, "ld-musl-aarch64.so.1") : null
44
+ const useLoader =
45
+ !bypassLoader &&
46
+ loader !== null &&
47
+ isTermux() &&
48
+ (os.platform() === "android" || process.platform === "android") &&
49
+ (os.arch() === "arm64" || process.arch === "arm64") &&
50
+ fs.existsSync(loader)
51
+ if (useLoader) {
52
+ delete env.LD_PRELOAD
53
+ delete env.LD_PRELOAD_64
54
+ env.LD_LIBRARY_PATH = binDir
24
55
  }
25
56
 
26
- const child = childProcess.spawn(target, process.argv.slice(2), {
27
- stdio: "inherit",
57
+ const command = useLoader ? loader : target
58
+ const args = useLoader ? [target, ...process.argv.slice(2)] : process.argv.slice(2)
59
+
60
+ const child = childProcess.spawn(command, args, {
61
+ stdio: ["inherit", "inherit", useLoader ? "pipe" : "inherit"],
28
62
  env,
29
63
  })
30
64
 
65
+ // Keep the loader's diagnostics visible while mirroring them to a buffer:
66
+ // a loader that refuses to start the program (e.g. the fixed load address
67
+ // of the non-PIE build is already taken by the loader's own mapping on
68
+ // some kernels) must trigger a PT_INTERP retry instead of a hard exit.
69
+ let loaderStderr = ""
70
+ if (useLoader && child.stderr) {
71
+ child.stderr.on("data", (chunk) => {
72
+ loaderStderr += chunk
73
+ process.stderr.write(chunk)
74
+ })
75
+ }
76
+
31
77
  let spawned = false
32
78
  let exited = false
33
79
 
@@ -37,6 +83,13 @@ function run(target) {
37
83
  // fall back to the next candidate (e.g. the musl build with its bundled
38
84
  // loader and libraries for Termux).
39
85
  if (error.code === "ENOENT" && !spawned && !exited) {
86
+ if (bypassLoader) {
87
+ // The PT_INTERP retry could not even be exec'd (the kernel cannot
88
+ // find the rewritten interpreter). Surface the loader-style error:
89
+ // nothing else can be tried for this candidate.
90
+ console.error(error.message)
91
+ process.exit(1)
92
+ }
40
93
  resolve(false)
41
94
  return
42
95
  }
@@ -72,6 +125,20 @@ function run(target) {
72
125
  return
73
126
  }
74
127
 
128
+ if (
129
+ !bypassLoader &&
130
+ useLoader &&
131
+ typeof code === "number" &&
132
+ code !== 0 &&
133
+ loaderFatal.test(loaderStderr)
134
+ ) {
135
+ // The bundled loader could not start the binary in this environment.
136
+ // Retry the same candidate through its (postinstall-rewritten) PT_INTERP
137
+ // with the same sanitized child environment.
138
+ run(target, env, true)
139
+ return
140
+ }
141
+
75
142
  process.exit(typeof code === "number" ? code : 0)
76
143
  })
77
144
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xyteeecode",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "xyteeecode - AI coding agent CLI",
5
5
  "license": "MIT",
6
6
  "homepage": "https://xyteee.com",
@@ -24,9 +24,9 @@
24
24
  "node": ">=18"
25
25
  },
26
26
  "optionalDependencies": {
27
- "xyteeecode-linux-arm64": "1.0.7",
28
- "xyteeecode-linux-x64": "1.0.7",
29
- "xyteeecode-linux-arm64-musl": "1.0.7",
30
- "xyteeecode-linux-x64-musl": "1.0.7"
27
+ "xyteeecode-linux-arm64": "1.0.9",
28
+ "xyteeecode-linux-x64": "1.0.9",
29
+ "xyteeecode-linux-arm64-musl": "1.0.9",
30
+ "xyteeecode-linux-x64-musl": "1.0.9"
31
31
  }
32
32
  }