cicy-code 2.1.46 → 2.1.48

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/bin/cicy-code.js CHANGED
@@ -1,96 +1,105 @@
1
1
  #!/usr/bin/env node
2
+ // Launcher for the npm distribution. Resolves the prebuilt binary that ships
3
+ // in the platform-specific optionalDependency (cicy-code-<os>-<cpu>) and execs
4
+ // it — no network, no postinstall download.
5
+ //
6
+ // Before exec it mirrors dev.py's startup: if PORT (default 8008) is already
7
+ // held by a *cicy-code* process it kills it and waits, so a stale instance
8
+ // never blocks the new one. A non-cicy occupant is left alone and we abort
9
+ // with a clear message (don't clobber someone else's server).
2
10
  const { spawn, execSync } = require('child_process');
3
- const path = require('path');
4
11
  const fs = require('fs');
5
- const https = require('https');
6
12
 
7
- const pkg = require('../package.json');
8
- const binPath = path.join(__dirname, 'cicy-code');
13
+ const PORT = process.env.PORT || '8008';
9
14
 
10
- const cn = process.argv.includes('--cn') || process.env.CN_MIRROR === '1';
11
-
12
- if (process.argv.includes('--cn')) {
13
- process.env.CN_MIRROR = '1';
15
+ const platformPkg = `cicy-code-${process.platform}-${process.arch}`;
16
+ let binPath;
17
+ try {
18
+ binPath = require.resolve(`${platformPkg}/cicy-code`);
19
+ } catch {
20
+ console.error(`cicy-code: no prebuilt binary for ${process.platform}-${process.arch}.`);
21
+ console.error(`The optional dependency "${platformPkg}" is not installed.`);
22
+ console.error(`Supported platforms: darwin-arm64, darwin-x64, linux-x64, linux-arm64.`);
23
+ console.error(`Reinstall: npm install -g cicy-code` +
24
+ ` (in China add --registry=https://registry.npmmirror.com)`);
25
+ process.exit(1);
14
26
  }
27
+ try { fs.chmodSync(binPath, 0o755); } catch {}
28
+
29
+ // --- dev.py-style port hygiene on PORT (default 8008) ----------------------
15
30
 
16
- if (cn) {
17
- console.log(' [mirror] Using Chinese mirrors (npm + GitHub proxy)');
31
+ function pidOnPort(port) {
32
+ // lsof first (macOS + Linux), then ss (Linux without lsof).
33
+ try {
34
+ const out = execSync(`lsof -ti TCP:${port} -sTCP:LISTEN`, {
35
+ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],
36
+ }).trim();
37
+ if (out) return out.split('\n')[0].trim();
38
+ } catch {}
39
+ try {
40
+ const out = execSync(`ss -tlnp 'sport = :${port}'`, {
41
+ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],
42
+ });
43
+ const m = out.match(/pid=(\d+)/);
44
+ if (m) return m[1];
45
+ } catch {}
46
+ return null;
18
47
  }
19
48
 
20
- // Check for updates
21
- function checkUpdate() {
22
- const registry = cn
23
- ? 'https://registry.npmmirror.com/cicy-code/latest'
24
- : 'https://registry.npmjs.org/cicy-code/latest';
25
- if (cn) console.log(` [mirror] Registry: registry.npmmirror.com`);
26
- return new Promise((resolve) => {
27
- https.get(registry, (res) => {
28
- let data = '';
29
- res.on('data', (c) => data += c);
30
- res.on('end', () => {
31
- try {
32
- const latest = JSON.parse(data).version;
33
- if (latest && latest !== pkg.version) {
34
- resolve(latest);
35
- } else {
36
- resolve(null);
37
- }
38
- } catch { resolve(null); }
39
- });
40
- }).on('error', () => resolve(null));
41
- });
49
+ function processCommand(pid) {
50
+ try {
51
+ return execSync(`ps -p ${pid} -o command=`, {
52
+ encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],
53
+ }).trim();
54
+ } catch { return ''; }
42
55
  }
43
56
 
44
- async function main() {
45
- // Check update (non-blocking, timeout 3s)
46
- const latest = await Promise.race([
47
- checkUpdate(),
48
- new Promise(r => setTimeout(() => r(null), 3000))
49
- ]);
57
+ function isAlive(pid) {
58
+ try { process.kill(Number(pid), 0); return true; }
59
+ catch (e) { return e.code === 'EPERM'; }
60
+ }
50
61
 
51
- if (latest && !process.env.CICY_SKIP_UPDATE) {
52
- console.log(`\n Update available: ${pkg.version} → ${latest}`);
53
- console.log(` Updating...\n`);
54
- try {
55
- const npmCmd = cn
56
- ? `npm install -g cicy-code@${latest} --registry=https://registry.npmmirror.com`
57
- : `npm install -g cicy-code@${latest}`;
58
- execSync(npmCmd, { stdio: 'inherit' });
59
- console.log(`\n Updated to ${latest}! Restarting...\n`);
60
- // Re-exec with new version
61
- const child = spawn('cicy-code', process.argv.slice(2), { stdio: 'inherit', env: process.env });
62
- child.on('exit', (code) => process.exit(code || 0));
63
- return;
64
- } catch (e) {
65
- console.log(` Update failed, running current version.\n`);
66
- }
62
+ function waitExit(pid, timeoutMs) {
63
+ const start = Date.now();
64
+ while (Date.now() - start < timeoutMs) {
65
+ if (!isAlive(pid)) return true;
66
+ try { execSync('sleep 0.2'); } catch {}
67
67
  }
68
+ return !isAlive(pid);
69
+ }
68
70
 
69
- // Install globally if not already
70
- try {
71
- const globalBin = execSync('npm prefix -g', { encoding: 'utf8' }).trim() + '/bin/cicy-code';
72
- if (!fs.existsSync(globalBin)) throw new Error('not installed');
73
- } catch {
74
- console.log(' Installing cicy-code globally...');
75
- try {
76
- const npmCmd = cn
77
- ? 'npm install -g cicy-code --registry=https://registry.npmmirror.com'
78
- : 'npm install -g cicy-code';
79
- execSync(npmCmd, { stdio: 'inherit' });
80
- console.log(' Installed! You can now run: cicy-code\n');
81
- } catch {}
82
- }
71
+ function killPid(pid) {
72
+ try { process.kill(Number(pid), 'SIGTERM'); }
73
+ catch (e) { if (e.code === 'ESRCH') return true; }
74
+ if (waitExit(pid, 6000)) return true;
75
+ try { process.kill(Number(pid), 'SIGKILL'); }
76
+ catch (e) { if (e.code === 'ESRCH') return true; }
77
+ return waitExit(pid, 2000);
78
+ }
83
79
 
84
- if (!fs.existsSync(binPath)) {
85
- console.error('Binary not found. Reinstall: npm install -g cicy-code');
80
+ const existing = pidOnPort(PORT);
81
+ if (existing) {
82
+ const cmd = processCommand(existing);
83
+ if (/cicy-code/.test(cmd)) {
84
+ console.log(`cicy-code: stopping existing instance on :${PORT} (pid=${existing})`);
85
+ if (!killPid(existing) || pidOnPort(PORT)) {
86
+ console.error(`cicy-code: port ${PORT} still in use after kill — aborting`);
87
+ process.exit(1);
88
+ }
89
+ } else {
90
+ console.error(`cicy-code: port ${PORT} is held by a non-cicy process (pid=${existing}): ${cmd}`);
91
+ console.error(`cicy-code: free it or set PORT=<other> — aborting`);
86
92
  process.exit(1);
87
93
  }
88
-
89
- const child = spawn(binPath, process.argv.slice(2), {
90
- stdio: 'inherit',
91
- env: process.env
92
- });
93
- child.on('exit', (code) => process.exit(code || 0));
94
94
  }
95
95
 
96
- main();
96
+ // --- launch ----------------------------------------------------------------
97
+
98
+ const child = spawn(binPath, process.argv.slice(2), {
99
+ stdio: 'inherit',
100
+ env: { ...process.env, PORT },
101
+ });
102
+ child.on('exit', (code, signal) => {
103
+ if (signal) process.kill(process.pid, signal);
104
+ else process.exit(code == null ? 0 : code);
105
+ });
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "2.1.46",
6
+ "version": "2.1.48",
7
7
  "description": "CiCy Code - AI-powered development environment",
8
8
  "author": {
9
9
  "name": "cicybot",
@@ -12,13 +12,15 @@
12
12
  "bin": {
13
13
  "cicy-code": "bin/cicy-code.js"
14
14
  },
15
- "scripts": {
16
- "postinstall": "node scripts/install.js"
17
- },
18
15
  "files": [
19
- "bin/cicy-code.js",
20
- "scripts/"
16
+ "bin/cicy-code.js"
21
17
  ],
18
+ "optionalDependencies": {
19
+ "cicy-code-darwin-arm64": "2.1.47",
20
+ "cicy-code-darwin-x64": "2.1.47",
21
+ "cicy-code-linux-x64": "2.1.47",
22
+ "cicy-code-linux-arm64": "2.1.47"
23
+ },
22
24
  "repository": {
23
25
  "type": "git",
24
26
  "url": "git+https://github.com/cicy-ai/cicy-code.git"
@@ -1,60 +0,0 @@
1
- const https = require('https');
2
- const fs = require('fs');
3
- const path = require('path');
4
-
5
- const VERSION = require('../package.json').version;
6
- const GH_URL = `https://github.com/cicy-ai/cicy-code/releases/download/v${VERSION}`;
7
- const CN_URL = `https://gh-proxy.com/https://github.com/cicy-ai/cicy-code/releases/download/v${VERSION}`;
8
-
9
- const cn = process.env.CN_MIRROR === '1' || process.argv.includes('--cn');
10
- const BASE_URL = cn ? CN_URL : GH_URL;
11
-
12
- const PLATFORMS = {
13
- 'darwin-arm64': 'cicy-code-darwin-arm64',
14
- 'darwin-x64': 'cicy-code-darwin-amd64',
15
- 'linux-x64': 'cicy-code-linux-amd64',
16
- 'linux-arm64': 'cicy-code-linux-arm64',
17
- };
18
-
19
- const key = `${process.platform}-${process.arch}`;
20
- const binName = PLATFORMS[key];
21
-
22
- if (!binName) {
23
- if (process.platform === 'win32') {
24
- console.error('Windows is not supported natively. Please use WSL:\n wsl --install\n wsl npx cicy-code');
25
- } else {
26
- console.error(`Unsupported platform: ${key}`);
27
- }
28
- process.exit(1);
29
- }
30
-
31
- const binDir = path.join(__dirname, '..', 'bin');
32
- const binPath = path.join(binDir, 'cicy-code');
33
- const url = `${BASE_URL}/${binName}`;
34
-
35
- console.log(`Downloading ${binName}${cn ? ' (CN mirror: gh-proxy.com)' : ''}...`);
36
- console.log(` URL: ${url}`);
37
-
38
- function download(url, dest, redirects = 5) {
39
- return new Promise((resolve, reject) => {
40
- if (redirects === 0) return reject(new Error('Too many redirects'));
41
- const proto = url.startsWith('https') ? https : require('http');
42
- proto.get(url, (res) => {
43
- if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
44
- return download(res.headers.location, dest, redirects - 1).then(resolve).catch(reject);
45
- }
46
- if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.statusCode}`));
47
- const file = fs.createWriteStream(dest);
48
- res.pipe(file);
49
- file.on('finish', () => { file.close(); fs.chmodSync(dest, 0o755); resolve(); });
50
- }).on('error', reject);
51
- });
52
- }
53
-
54
- download(url, binPath)
55
- .then(() => console.log('Done!'))
56
- .catch((err) => {
57
- console.error('Download failed:', err.message);
58
- if (!cn) console.error('Try: CN_MIRROR=1 npx cicy-code');
59
- process.exit(1);
60
- });