@bash0816/copilot-termux 1.0.65 → 1.0.68
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 +4 -4
- package/bin/copilot +30 -26
- package/bin/copilot-termux +4 -1
- package/config/copilot-termux-release-manifest.json +15 -0
- package/config/manifest.json +6 -2
- package/lib/check-updates.js +183 -0
- package/lib/platform-patch.js +555 -140
- package/lib/setup.js +74 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -6,10 +6,10 @@ Termux (Android aarch64) 向け GitHub Copilot CLI パッケージです。
|
|
|
6
6
|
|
|
7
7
|
## Status / 状態
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
- `copilot -p`: **available**
|
|
11
|
-
- TUI (`copilot`): **available**
|
|
12
|
-
- MCP: **available**
|
|
9
|
+
- **@latest**: `1.0.65-1`(recommended / 推奨。1.0.65 の TUI login regression・`/update`参照先・起動時通知バナーの問題を修正済み)
|
|
10
|
+
- `copilot -p`: **available** ✅(1.0.65-1)
|
|
11
|
+
- TUI (`copilot`): **available** ✅(1.0.65-1)
|
|
12
|
+
- MCP: **available** ✅(1.0.65-1)
|
|
13
13
|
|
|
14
14
|
## Install / インストール
|
|
15
15
|
|
package/bin/copilot
CHANGED
|
@@ -11,8 +11,14 @@ _COMPAT="${PACKAGE_DIR}/lib/bionic-compat.so"
|
|
|
11
11
|
[ -f "${_COMPAT}" ] || { echo '[copilot-termux] ERROR: lib/bionic-compat.so missing. Reinstall package.' >&2; exit 1; }
|
|
12
12
|
PRELOAD="${_COMPAT}${LD_PRELOAD:+:${LD_PRELOAD}}"
|
|
13
13
|
|
|
14
|
+
if [ "${1:-}" = "update" ]; then
|
|
15
|
+
shift
|
|
16
|
+
exec node "${PACKAGE_DIR}/lib/check-updates.js" update "$@"
|
|
17
|
+
fi
|
|
18
|
+
|
|
14
19
|
CACHE_DIR="${HOME}/.copilot-termux"
|
|
15
20
|
CURRENT="${CACHE_DIR}/current"
|
|
21
|
+
PREFIX="${PREFIX:-/data/data/com.termux/files/usr}"
|
|
16
22
|
|
|
17
23
|
if [ ! -d "${CURRENT}" ]; then
|
|
18
24
|
echo "[copilot-termux] Not set up. Run: copilot-termux setup" >&2
|
|
@@ -30,40 +36,38 @@ if [ -d "${MXC_WRAP}/arm64" ] && [ -x "${MXC_WRAP}/arm64/lxc-exec" ]; then
|
|
|
30
36
|
export MXC_BIN_DIR="${MXC_WRAP}"
|
|
31
37
|
fi
|
|
32
38
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
MAGI_NODE_MAJOR="${MAGI_NODE_VERSION%%.*}"
|
|
39
|
-
fi
|
|
39
|
+
# glibc mode: glibc Node.js + glibc runtime.node + platform-patch.js (authManager* stubs still needed)
|
|
40
|
+
_GLIBC_LD="${PREFIX}/glibc/lib/ld-linux-aarch64.so.1"
|
|
41
|
+
_GLIBC_LIBS="${PREFIX}/glibc/lib"
|
|
42
|
+
_GLIBC_RUNTIME="${CURRENT}/prebuilds/linux-arm64/runtime.node"
|
|
43
|
+
_GLIBC_NODE_AUTO="${CACHE_DIR}/glibc-node/node"
|
|
40
44
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"$@"
|
|
48
|
-
;;
|
|
49
|
-
esac
|
|
45
|
+
_USE_GLIBC_NODE=""
|
|
46
|
+
if [ -n "${MAGI_NODE:-}" ] && [ -x "${MAGI_NODE}" ]; then
|
|
47
|
+
_USE_GLIBC_NODE="${MAGI_NODE}"
|
|
48
|
+
elif [ -x "${_GLIBC_NODE_AUTO}" ]; then
|
|
49
|
+
_USE_GLIBC_NODE="${_GLIBC_NODE_AUTO}"
|
|
50
|
+
fi
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
if [ -n "${_USE_GLIBC_NODE}" ] && [ -f "${_GLIBC_RUNTIME}" ] && [ -f "${_GLIBC_LD}" ]; then
|
|
53
|
+
_SSL_CERT="${PREFIX}/etc/tls/cert.pem"
|
|
54
|
+
_SSL_CERT_DIR="${PREFIX}/etc/tls"
|
|
55
|
+
if [ ! -r "${_SSL_CERT}" ]; then
|
|
56
|
+
echo "[copilot-termux] ERROR: CA bundle not readable: ${_SSL_CERT}" >&2
|
|
57
|
+
echo "[copilot-termux] Run: pkg install ca-certificates" >&2
|
|
58
|
+
exit 1
|
|
57
59
|
fi
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"${
|
|
60
|
+
exec env LD_PRELOAD="" COPILOT_TERMUX_GLIBC_MODE=1 \
|
|
61
|
+
SSL_CERT_FILE="${_SSL_CERT}" \
|
|
62
|
+
SSL_CERT_DIR="${_SSL_CERT_DIR}" \
|
|
63
|
+
"${_GLIBC_LD}" --library-path "${_GLIBC_LIBS}" \
|
|
64
|
+
"${_USE_GLIBC_NODE}" \
|
|
62
65
|
--require "${PACKAGE_DIR}/lib/platform-patch.js" \
|
|
63
66
|
"${COPILOT_INDEX}" \
|
|
64
67
|
"$@"
|
|
65
68
|
fi
|
|
66
69
|
|
|
70
|
+
# bionic fallback
|
|
67
71
|
LD_PRELOAD="${PRELOAD}" exec node \
|
|
68
72
|
--require "${PACKAGE_DIR}/lib/platform-patch.js" \
|
|
69
73
|
"${COPILOT_INDEX}" \
|
package/bin/copilot-termux
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
const { setup } = require('../lib/setup');
|
|
4
|
+
const { runUpdate } = require('../lib/check-updates');
|
|
4
5
|
const cmd = process.argv[2];
|
|
5
|
-
if (cmd === 'setup'
|
|
6
|
+
if (cmd === 'setup') {
|
|
6
7
|
setup().then(() => process.exit(0)).catch(e => { console.error(e.message); process.exit(1); });
|
|
8
|
+
} else if (cmd === 'update') {
|
|
9
|
+
runUpdate().then(code => process.exit(code)).catch(e => { console.error(e.message); process.exit(1); });
|
|
7
10
|
} else {
|
|
8
11
|
console.log('Usage: copilot-termux <setup|update>');
|
|
9
12
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifest_version": 1,
|
|
3
|
+
"package_name": "@bash0816/copilot-termux",
|
|
4
|
+
"copilot_version": "1.0.68",
|
|
5
|
+
"latest_audited_version": "1.0.65-1",
|
|
6
|
+
"latest_candidate_version": "1.0.68",
|
|
7
|
+
"previous_stable_version": "1.0.63",
|
|
8
|
+
"candidate_state": "none",
|
|
9
|
+
"canonical_package_status": "not_published",
|
|
10
|
+
"public_distribution_status": "staged",
|
|
11
|
+
"nodejs_glibc_version": "node-glibc-v24.15.0",
|
|
12
|
+
"build_run_id": null,
|
|
13
|
+
"last_updated": "2026-07-02",
|
|
14
|
+
"manifest_url": "https://raw.githubusercontent.com/bash0816/Github-Copilot-Termux/main/packages/copilot-termux/config/copilot-termux-release-manifest.json"
|
|
15
|
+
}
|
package/config/manifest.json
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
"wrapperVersion": "2.0.0",
|
|
3
3
|
"copilot": {
|
|
4
4
|
"package": "@github/copilot-linuxmusl-arm64",
|
|
5
|
-
"version": "1.0.
|
|
6
|
-
"integrity": "sha512-
|
|
5
|
+
"version": "1.0.68",
|
|
6
|
+
"integrity": "sha512-LTYZFOHpeLg4rCtsq3A/LMZxxRKFcCLmhnt8F7ovNYLNDJMkh3xdYanoXP0C0PO3uyUMiNJ+p5YXhZiBuo2yfw=="
|
|
7
|
+
},
|
|
8
|
+
"glibcNode": {
|
|
9
|
+
"version": "26.2.0",
|
|
10
|
+
"sha256": "bf52461d25017479cdc549642c4e7a2303ac5c5395d7c3d026d5d8b3fa283c05"
|
|
7
11
|
}
|
|
8
12
|
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const cp = require('child_process');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const https = require('https');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
const packageDir = path.resolve(__dirname, '..');
|
|
9
|
+
const pkg = require(path.join(packageDir, 'package.json'));
|
|
10
|
+
const currentVersion = pkg.version;
|
|
11
|
+
const packageName = pkg.name; // @bash0816/copilot-termux
|
|
12
|
+
|
|
13
|
+
// prefix は __dirname から動的に取得。
|
|
14
|
+
// __dirname = <prefix>/lib/node_modules/@bash0816/copilot-termux/lib
|
|
15
|
+
// prefix = <prefix>
|
|
16
|
+
// つまり 5 段上
|
|
17
|
+
const npmPrefix = path.resolve(__dirname, '../../../../..');
|
|
18
|
+
|
|
19
|
+
const cacheRoot = path.join(os.homedir(), '.copilot-termux');
|
|
20
|
+
const cacheFile = path.join(cacheRoot, 'update-check.json');
|
|
21
|
+
const ttlMs = 24 * 60 * 60 * 1000;
|
|
22
|
+
|
|
23
|
+
// --- semver 軽量実装(依存なし) ---
|
|
24
|
+
// バージョン文字列を [major, minor, patch, pre] に分解して比較
|
|
25
|
+
function parseVer(v) {
|
|
26
|
+
// 例: "1.0.65-1" -> { nums: [1,0,65], pre: "1" }
|
|
27
|
+
// "1.0.65" -> { nums: [1,0,65], pre: null }
|
|
28
|
+
const [base, ...preParts] = v.split('-');
|
|
29
|
+
const nums = base.split('.').map(Number);
|
|
30
|
+
const pre = preParts.length > 0 ? preParts.join('-') : null;
|
|
31
|
+
return { nums, pre };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// このプロジェクトの prerelease 表記は x.y.z-N(N は数字のみ)を前提としており、
|
|
35
|
+
// 汎用 semver のような英数混在 prerelease 識別子の比較は想定していません。
|
|
36
|
+
// returns negative if a < b, 0 if equal, positive if a > b
|
|
37
|
+
function compareVersions(a, b) {
|
|
38
|
+
const pa = parseVer(a);
|
|
39
|
+
const pb = parseVer(b);
|
|
40
|
+
for (let i = 0; i < 3; i++) {
|
|
41
|
+
const na = pa.nums[i] || 0;
|
|
42
|
+
const nb = pb.nums[i] || 0;
|
|
43
|
+
if (na !== nb) return na - nb;
|
|
44
|
+
}
|
|
45
|
+
// prerelease: no pre = stable > has pre (semver spec)
|
|
46
|
+
if (pa.pre === null && pb.pre !== null) return 1;
|
|
47
|
+
if (pa.pre !== null && pb.pre === null) return -1;
|
|
48
|
+
if (pa.pre !== null && pb.pre !== null) {
|
|
49
|
+
const aParts = pa.pre.split('.');
|
|
50
|
+
const bParts = pb.pre.split('.');
|
|
51
|
+
const len = Math.max(aParts.length, bParts.length);
|
|
52
|
+
for (let j = 0; j < len; j++) {
|
|
53
|
+
const ap = aParts[j], bp = bParts[j];
|
|
54
|
+
if (ap === undefined) return -1;
|
|
55
|
+
if (bp === undefined) return 1;
|
|
56
|
+
const an = Number(ap), bn = Number(bp);
|
|
57
|
+
if (!isNaN(an) && !isNaN(bn)) {
|
|
58
|
+
if (an !== bn) return an - bn;
|
|
59
|
+
} else {
|
|
60
|
+
if (ap < bp) return -1;
|
|
61
|
+
if (ap > bp) return 1;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function isPrerelease(v) {
|
|
70
|
+
return v.includes('-');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function readCache() {
|
|
74
|
+
try { return JSON.parse(fs.readFileSync(cacheFile, 'utf8')); } catch { return {}; }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function writeCache(data) {
|
|
78
|
+
fs.mkdirSync(cacheRoot, { recursive: true });
|
|
79
|
+
fs.writeFileSync(cacheFile, JSON.stringify(data, null, 2) + '\n');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function fetchVersion(tag) {
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}/${encodeURIComponent(tag)}`;
|
|
85
|
+
const req = https.get(url, { timeout: 5000 }, res => {
|
|
86
|
+
if (res.statusCode !== 200) { res.resume(); reject(new Error(`HTTP ${res.statusCode}`)); return; }
|
|
87
|
+
let body = '';
|
|
88
|
+
res.on('data', c => { body += c; });
|
|
89
|
+
res.on('end', () => {
|
|
90
|
+
try { resolve(JSON.parse(body).version); } catch (e) { reject(e); }
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
req.on('timeout', () => req.destroy(new Error('timeout')));
|
|
94
|
+
req.on('error', reject);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function resolveTarget() {
|
|
99
|
+
const latestVer = await fetchVersion('latest');
|
|
100
|
+
|
|
101
|
+
let bestVer = latestVer;
|
|
102
|
+
|
|
103
|
+
// current が prerelease または current > latest の場合のみ candidate も確認
|
|
104
|
+
if (isPrerelease(currentVersion) || compareVersions(currentVersion, latestVer) > 0) {
|
|
105
|
+
try {
|
|
106
|
+
const candidateVer = await fetchVersion('candidate');
|
|
107
|
+
// latest と candidate のうちより新しい方を bestVer とする
|
|
108
|
+
if (compareVersions(candidateVer, bestVer) > 0) {
|
|
109
|
+
bestVer = candidateVer;
|
|
110
|
+
}
|
|
111
|
+
} catch {
|
|
112
|
+
// candidate タグ取得失敗は無視
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (compareVersions(bestVer, currentVersion) <= 0) return null;
|
|
117
|
+
return bestVer;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function installVersion(targetVer) {
|
|
121
|
+
const spec = `${packageName}@${targetVer}`;
|
|
122
|
+
const dryRun = process.argv.includes('--dry-run');
|
|
123
|
+
if (dryRun) {
|
|
124
|
+
console.log(`npm install -g --prefix ${npmPrefix} ${spec}`);
|
|
125
|
+
return 0;
|
|
126
|
+
}
|
|
127
|
+
console.error(`Updating to ${targetVer}...`);
|
|
128
|
+
const result = cp.spawnSync('npm', ['install', '-g', '--prefix', npmPrefix, spec], {
|
|
129
|
+
stdio: 'inherit',
|
|
130
|
+
env: { ...process.env, DISABLE_INSTALLATION_CHECKS: 'true' },
|
|
131
|
+
});
|
|
132
|
+
if (result.status !== 0) {
|
|
133
|
+
console.error(`\nUpdate failed. Run manually:\n DISABLE_INSTALLATION_CHECKS=true npm install -g --prefix ${npmPrefix} ${spec}`);
|
|
134
|
+
}
|
|
135
|
+
return result.status === null ? 1 : result.status;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function runUpdate() {
|
|
139
|
+
let targetVer;
|
|
140
|
+
try {
|
|
141
|
+
targetVer = await resolveTarget();
|
|
142
|
+
} catch (e) {
|
|
143
|
+
console.error(`Failed to check for updates: ${e.message}`);
|
|
144
|
+
console.error(`Run manually: DISABLE_INSTALLATION_CHECKS=true npm install -g --prefix ${npmPrefix} ${packageName}@latest`);
|
|
145
|
+
return 1;
|
|
146
|
+
}
|
|
147
|
+
if (!targetVer) {
|
|
148
|
+
console.error(`Already on latest version: ${currentVersion}`);
|
|
149
|
+
return 0;
|
|
150
|
+
}
|
|
151
|
+
return installVersion(targetVer);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function runNotify() {
|
|
155
|
+
const cache = readCache();
|
|
156
|
+
const now = Date.now();
|
|
157
|
+
// TTL キャッシュ: 24h 以内に確認済みならスキップ
|
|
158
|
+
if (cache.notifyCheckedAt && now - cache.notifyCheckedAt < ttlMs) return 0;
|
|
159
|
+
|
|
160
|
+
let targetVer;
|
|
161
|
+
try {
|
|
162
|
+
targetVer = await resolveTarget();
|
|
163
|
+
writeCache({ ...cache, notifyCheckedAt: now });
|
|
164
|
+
} catch {
|
|
165
|
+
return 0; // 失敗は無視(stderr を汚さない)
|
|
166
|
+
}
|
|
167
|
+
if (!targetVer) return 0;
|
|
168
|
+
console.error(`Update available: ${currentVersion} → ${targetVer}`);
|
|
169
|
+
console.error('Run: copilot update');
|
|
170
|
+
return 0;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
module.exports = { runUpdate, runNotify };
|
|
174
|
+
|
|
175
|
+
// CLI entry
|
|
176
|
+
if (require.main === module) {
|
|
177
|
+
const mode = process.argv[2] || 'notify';
|
|
178
|
+
const fn = mode === 'update' ? runUpdate : runNotify;
|
|
179
|
+
fn().then(code => { process.exitCode = code; }).catch(e => {
|
|
180
|
+
console.error(e.message);
|
|
181
|
+
process.exit(1);
|
|
182
|
+
});
|
|
183
|
+
}
|