@bash0816/copilot-termux 1.0.65 → 1.0.68-1

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
@@ -6,10 +6,10 @@ Termux (Android aarch64) 向け GitHub Copilot CLI パッケージです。
6
6
 
7
7
  ## Status / 状態
8
8
 
9
- - version: `1.0.63`
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,63 @@ 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
- if [ -n "${MAGI_NODE:-}" ]; then
34
- MAGI_NODE_VERSION="$("${MAGI_NODE}" --version 2>/dev/null || true)"
35
- MAGI_NODE_MAJOR=""
36
- if [ -n "${MAGI_NODE_VERSION}" ]; then
37
- MAGI_NODE_VERSION="${MAGI_NODE_VERSION#v}"
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_CLI_NATIVE="${CURRENT}/prebuilds/linux-arm64/cli-native.node"
44
+ _GLIBC_NODE_AUTO="${CACHE_DIR}/glibc-node/node"
45
+
46
+ _USE_GLIBC_NODE=""
47
+ if [ -n "${MAGI_NODE:-}" ] && [ -x "${MAGI_NODE}" ]; then
48
+ _USE_GLIBC_NODE="${MAGI_NODE}"
49
+ elif [ -x "${_GLIBC_NODE_AUTO}" ]; then
50
+ _USE_GLIBC_NODE="${_GLIBC_NODE_AUTO}"
51
+ fi
40
52
 
41
- case "${MAGI_NODE_MAJOR}" in
42
- ''|*[!0-9]*)
43
- echo "[copilot-termux] MAGI_NODE version check failed; falling back to node" >&2
44
- LD_PRELOAD="${PRELOAD}" exec node \
45
- --require "${PACKAGE_DIR}/lib/platform-patch.js" \
46
- "${COPILOT_INDEX}" \
47
- "$@"
48
- ;;
49
- esac
53
+ _GLIBC_READY=1
54
+ [ -n "${_USE_GLIBC_NODE}" ] || _GLIBC_READY=0
55
+ [ -f "${_GLIBC_RUNTIME}" ] || _GLIBC_READY=0
56
+ [ -f "${_GLIBC_CLI_NATIVE}" ] || _GLIBC_READY=0
57
+ [ -f "${_GLIBC_LD}" ] || _GLIBC_READY=0
50
58
 
51
- if [ "${MAGI_NODE_MAJOR}" -lt 24 ]; then
52
- echo "[copilot-termux] MAGI_NODE ${MAGI_NODE_VERSION} is below v24; falling back to node" >&2
53
- LD_PRELOAD="${PRELOAD}" exec node \
54
- --require "${PACKAGE_DIR}/lib/platform-patch.js" \
55
- "${COPILOT_INDEX}" \
56
- "$@"
57
- fi
59
+ _GLIBC_ANY=0
60
+ [ -n "${_USE_GLIBC_NODE}" ] && _GLIBC_ANY=1
61
+ [ -f "${_GLIBC_RUNTIME}" ] && _GLIBC_ANY=1
62
+ [ -f "${_GLIBC_CLI_NATIVE}" ] && _GLIBC_ANY=1
63
+ [ -f "${_GLIBC_LD}" ] && _GLIBC_ANY=1
58
64
 
59
- exec env -u LD_LIBRARY_PATH \
60
- LD_PRELOAD="${PRELOAD}" \
61
- "${MAGI_NODE}" \
65
+ if [ "${_GLIBC_READY}" = "1" ]; then
66
+ _SSL_CERT="${PREFIX}/etc/tls/cert.pem"
67
+ _SSL_CERT_DIR="${PREFIX}/etc/tls"
68
+ if [ ! -r "${_SSL_CERT}" ]; then
69
+ echo "[copilot-termux] ERROR: CA bundle not readable: ${_SSL_CERT}" >&2
70
+ echo "[copilot-termux] Run: pkg install ca-certificates" >&2
71
+ exit 1
72
+ fi
73
+ exec env LD_PRELOAD="" COPILOT_TERMUX_GLIBC_MODE=1 \
74
+ SSL_CERT_FILE="${_SSL_CERT}" \
75
+ SSL_CERT_DIR="${_SSL_CERT_DIR}" \
76
+ "${_GLIBC_LD}" --library-path "${_GLIBC_LIBS}" \
77
+ "${_USE_GLIBC_NODE}" \
62
78
  --require "${PACKAGE_DIR}/lib/platform-patch.js" \
63
79
  "${COPILOT_INDEX}" \
64
80
  "$@"
81
+ elif [ "${_GLIBC_ANY}" = "1" ]; then
82
+ # 注: システムの glibc-repo パッケージ(_GLIBC_LD)を別目的で入れているだけで
83
+ # copilot-termux 自身の glibc mode セットアップ(setup.js の setupGlibcRuntime/setupGlibcNode)が
84
+ # 未完の場合も、ここでは「glibc mode 設定が部分的」としてエラー扱いにする。
85
+ # これは意図的な判断(Free auto mode の既知の壊れた bionic 経路への黙示的フォールバックを防ぐため)。
86
+ echo "[copilot-termux] ERROR: glibc mode partially configured. Missing:" >&2
87
+ [ -n "${_USE_GLIBC_NODE}" ] || echo " - glibc node (${_GLIBC_NODE_AUTO})" >&2
88
+ [ -f "${_GLIBC_RUNTIME}" ] || echo " - glibc runtime.node (${_GLIBC_RUNTIME})" >&2
89
+ [ -f "${_GLIBC_CLI_NATIVE}" ] || echo " - glibc cli-native.node (${_GLIBC_CLI_NATIVE})" >&2
90
+ [ -f "${_GLIBC_LD}" ] || echo " - glibc loader (${_GLIBC_LD})" >&2
91
+ echo "[copilot-termux] Run: copilot-termux setup" >&2
92
+ exit 1
65
93
  fi
66
94
 
95
+ # bionic fallback(glibc関連ファイルが一つも無い場合のみ。意図的なbionic-onlyの正当な状態)
67
96
  LD_PRELOAD="${PRELOAD}" exec node \
68
97
  --require "${PACKAGE_DIR}/lib/platform-patch.js" \
69
98
  "${COPILOT_INDEX}" \
@@ -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' || cmd === 'update') {
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-1",
5
+ "latest_audited_version": "1.0.68-1",
6
+ "latest_candidate_version": "1.0.68",
7
+ "previous_stable_version": "1.0.65-1",
8
+ "candidate_state": "promoted",
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-07",
14
+ "manifest_url": "https://raw.githubusercontent.com/bash0816/Github-Copilot-Termux/main/packages/copilot-termux/config/copilot-termux-release-manifest.json"
15
+ }
@@ -2,7 +2,11 @@
2
2
  "wrapperVersion": "2.0.0",
3
3
  "copilot": {
4
4
  "package": "@github/copilot-linuxmusl-arm64",
5
- "version": "1.0.64",
6
- "integrity": "sha512-C+EYoMvmlUxR0YYxLkD3nwn940y0zId8z+pPl9rFO6f9heMGXYCwCZL2i2c3GW6CvGgZF6Wbzw1Kk0Gvw46F2w=="
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,174 @@
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
+ // このプロジェクトの `-N` サフィックスは、汎用 semver のプレリリース識別子ではなく、
35
+ // 「正式版リリース後に追加したfork独自パッチのリビジョン番号」を意味する。
36
+ // suffixなし = revision 0、`-N` = revision N として扱い、Nが大きいほど新しい。
37
+ // (例: 1.0.68 < 1.0.68-1 < 1.0.68-2)
38
+ // returns negative if a < b, 0 if equal, positive if a > b
39
+ function compareVersions(a, b) {
40
+ const pa = parseVer(a);
41
+ const pb = parseVer(b);
42
+ for (let i = 0; i < 3; i++) {
43
+ const na = pa.nums[i] || 0;
44
+ const nb = pb.nums[i] || 0;
45
+ if (na !== nb) return na - nb;
46
+ }
47
+ // このフォークの `-N` サフィックスは一般semverの「正式版より前のプレリリース」ではなく、
48
+ // 「正式版リリース後に追加したfork独自パッチのリビジョン番号」を意味する。
49
+ // suffixなし = revision 0、`-N` = revision N として扱い、Nが大きいほど新しいとみなす。
50
+ // (例: 1.0.68 < 1.0.68-1 < 1.0.68-2)
51
+ // parseVer前提: N は数字のみ(本ファイル冒頭コメントの前提を踏襲)。
52
+ const ra = pa.pre === null ? 0 : Number(pa.pre);
53
+ const rb = pb.pre === null ? 0 : Number(pb.pre);
54
+ return ra - rb;
55
+ }
56
+
57
+ function isPrerelease(v) {
58
+ return v.includes('-');
59
+ }
60
+
61
+ function readCache() {
62
+ try { return JSON.parse(fs.readFileSync(cacheFile, 'utf8')); } catch { return {}; }
63
+ }
64
+
65
+ function writeCache(data) {
66
+ fs.mkdirSync(cacheRoot, { recursive: true });
67
+ fs.writeFileSync(cacheFile, JSON.stringify(data, null, 2) + '\n');
68
+ }
69
+
70
+ function fetchVersion(tag) {
71
+ return new Promise((resolve, reject) => {
72
+ const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}/${encodeURIComponent(tag)}`;
73
+ const req = https.get(url, { timeout: 5000 }, res => {
74
+ if (res.statusCode !== 200) { res.resume(); reject(new Error(`HTTP ${res.statusCode}`)); return; }
75
+ let body = '';
76
+ res.on('data', c => { body += c; });
77
+ res.on('end', () => {
78
+ try { resolve(JSON.parse(body).version); } catch (e) { reject(e); }
79
+ });
80
+ });
81
+ req.on('timeout', () => req.destroy(new Error('timeout')));
82
+ req.on('error', reject);
83
+ });
84
+ }
85
+
86
+ async function resolveTarget() {
87
+ const latestVer = await fetchVersion('latest');
88
+
89
+ let bestVer = latestVer;
90
+
91
+ // current が prerelease または current > latest の場合のみ candidate も確認
92
+ if (isPrerelease(currentVersion) || compareVersions(currentVersion, latestVer) > 0) {
93
+ try {
94
+ const candidateVer = await fetchVersion('candidate');
95
+ // latest と candidate のうちより新しい方を bestVer とする
96
+ if (compareVersions(candidateVer, bestVer) > 0) {
97
+ bestVer = candidateVer;
98
+ }
99
+ } catch {
100
+ // candidate タグ取得失敗は無視
101
+ }
102
+ }
103
+
104
+ if (compareVersions(bestVer, currentVersion) <= 0) return null;
105
+ return bestVer;
106
+ }
107
+
108
+ function installVersion(targetVer) {
109
+ const spec = `${packageName}@${targetVer}`;
110
+ const dryRun = process.argv.includes('--dry-run');
111
+ if (dryRun) {
112
+ console.log(`npm install -g --prefix ${npmPrefix} ${spec}`);
113
+ return 0;
114
+ }
115
+ console.error(`Updating to ${targetVer}...`);
116
+ const result = cp.spawnSync('npm', ['install', '-g', '--prefix', npmPrefix, spec], {
117
+ stdio: 'inherit',
118
+ env: { ...process.env, DISABLE_INSTALLATION_CHECKS: 'true' },
119
+ });
120
+ if (result.status !== 0) {
121
+ console.error(`\nUpdate failed. Run manually:\n DISABLE_INSTALLATION_CHECKS=true npm install -g --prefix ${npmPrefix} ${spec}`);
122
+ }
123
+ return result.status === null ? 1 : result.status;
124
+ }
125
+
126
+ async function runUpdate() {
127
+ let targetVer;
128
+ try {
129
+ targetVer = await resolveTarget();
130
+ } catch (e) {
131
+ console.error(`Failed to check for updates: ${e.message}`);
132
+ console.error(`Run manually: DISABLE_INSTALLATION_CHECKS=true npm install -g --prefix ${npmPrefix} ${packageName}@latest`);
133
+ return 1;
134
+ }
135
+ if (!targetVer) {
136
+ console.error(`Already on latest version: ${currentVersion}`);
137
+ return 0;
138
+ }
139
+ return installVersion(targetVer);
140
+ }
141
+
142
+ async function runNotify() {
143
+ const cache = readCache();
144
+ const now = Date.now();
145
+ // TTL キャッシュ: 24h 以内に確認済みならスキップ
146
+ if (cache.notifyCheckedAt && now - cache.notifyCheckedAt < ttlMs) return 0;
147
+
148
+ let targetVer;
149
+ try {
150
+ targetVer = await resolveTarget();
151
+ writeCache({ ...cache, notifyCheckedAt: now });
152
+ } catch {
153
+ return 0; // 失敗は無視(stderr を汚さない)
154
+ }
155
+ if (!targetVer) return 0;
156
+ console.error(`Update available: ${currentVersion} → ${targetVer}`);
157
+ console.error('Run: copilot update');
158
+ return 0;
159
+ }
160
+
161
+ module.exports = { runUpdate, runNotify };
162
+
163
+ // テスト専用export・CLI実行経路には影響しない(node:test用)
164
+ module.exports.__test = { compareVersions };
165
+
166
+ // CLI entry
167
+ if (require.main === module) {
168
+ const mode = process.argv[2] || 'notify';
169
+ const fn = mode === 'update' ? runUpdate : runNotify;
170
+ fn().then(code => { process.exitCode = code; }).catch(e => {
171
+ console.error(e.message);
172
+ process.exit(1);
173
+ });
174
+ }