@aion0/forge 0.2.23 → 0.2.25

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.
@@ -104,6 +104,8 @@ if (resetTerminal) {
104
104
  }
105
105
 
106
106
  // ── Kill orphan standalone processes ──
107
+ const protectedPids = new Set();
108
+
107
109
  function cleanupOrphans() {
108
110
  try {
109
111
  const out = execSync("ps aux | grep -E 'telegram-standalone|terminal-standalone|next-server|next start|next dev' | grep -v grep | awk '{print $2}'", {
@@ -112,14 +114,17 @@ function cleanupOrphans() {
112
114
  if (out) {
113
115
  const myPid = String(process.pid);
114
116
  for (const pid of out.split('\n').filter(Boolean)) {
115
- if (pid.trim() === myPid) continue; // don't kill ourselves
116
- try { process.kill(parseInt(pid), 'SIGTERM'); } catch {}
117
+ const p = pid.trim();
118
+ if (p === myPid) continue;
119
+ if (protectedPids.has(p)) continue; // don't kill processes we just started
120
+ try { process.kill(parseInt(p), 'SIGTERM'); } catch {}
117
121
  }
118
- // Force kill any remaining
119
122
  setTimeout(() => {
120
123
  for (const pid of out.split('\n').filter(Boolean)) {
121
- if (pid.trim() === myPid) continue;
122
- try { process.kill(parseInt(pid), 'SIGKILL'); } catch {}
124
+ const p = pid.trim();
125
+ if (p === myPid) continue;
126
+ if (protectedPids.has(p)) continue;
127
+ try { process.kill(parseInt(p), 'SIGKILL'); } catch {}
123
128
  }
124
129
  }, 2000);
125
130
  console.log('[forge] Cleaned up orphan processes');
@@ -187,7 +192,8 @@ function startBackground() {
187
192
  }
188
193
 
189
194
  const logFd = openSync(LOG_FILE, 'a');
190
- const child = spawn('npx', ['next', 'start', '-p', String(webPort)], {
195
+ const nextBin = join(ROOT, 'node_modules', '.bin', 'next');
196
+ const child = spawn(nextBin, ['start', '-p', String(webPort)], {
191
197
  cwd: ROOT,
192
198
  stdio: ['ignore', logFd, logFd],
193
199
  env: { ...process.env, FORGE_EXTERNAL_SERVICES: '1' },
@@ -195,9 +201,10 @@ function startBackground() {
195
201
  });
196
202
 
197
203
  writeFileSync(PID_FILE, String(child.pid));
204
+ protectedPids.add(String(child.pid));
198
205
  child.unref();
199
206
 
200
- // Start services in background too
207
+ // Start services in background too (cleanupOrphans will skip protectedPids)
201
208
  startServices();
202
209
 
203
210
  console.log(`[forge] Started in background (pid ${child.pid})`);
@@ -217,8 +224,18 @@ if (isStop) {
217
224
  // ── Restart ──
218
225
  if (isRestart) {
219
226
  stopServer();
220
- // Brief delay to let port release
221
- await new Promise(r => setTimeout(r, 1500));
227
+ // Wait for port to fully release
228
+ const net = await import('node:net');
229
+ for (let i = 0; i < 20; i++) {
230
+ await new Promise(r => setTimeout(r, 500));
231
+ const free = await new Promise(resolve => {
232
+ const s = net.createServer();
233
+ s.once('error', () => resolve(false));
234
+ s.once('listening', () => { s.close(); resolve(true); });
235
+ s.listen(webPort);
236
+ });
237
+ if (free) break;
238
+ }
222
239
  startBackground();
223
240
  process.exit(0);
224
241
  }
package/cli/mw.ts CHANGED
@@ -480,8 +480,20 @@ async function main() {
480
480
  } else {
481
481
  console.log('[forge] Upgrading from npm...');
482
482
  try {
483
- execSync('cd /tmp && npm install -g @aion0/forge', { stdio: 'inherit' });
484
- console.log('[forge] Upgraded. Run: forge server restart');
483
+ const { homedir } = await import('node:os');
484
+ execSync('npm install -g @aion0/forge@latest --prefer-online', {
485
+ stdio: 'inherit',
486
+ cwd: homedir(),
487
+ });
488
+ // Show installed version
489
+ try {
490
+ const { readFileSync } = await import('node:fs');
491
+ const globalRoot = execSync('npm root -g', { encoding: 'utf-8', cwd: homedir() }).trim();
492
+ const pkg = JSON.parse(readFileSync(join(globalRoot, '@aion0', 'forge', 'package.json'), 'utf-8'));
493
+ console.log(`[forge] Upgraded to v${pkg.version}. Run: forge server restart`);
494
+ } catch {
495
+ console.log('[forge] Upgraded. Run: forge server restart');
496
+ }
485
497
  } catch {
486
498
  console.log('[forge] Upgrade failed');
487
499
  }
@@ -128,7 +128,7 @@ export default function Dashboard({ user }: { user: any }) {
128
128
  {versionInfo.hasUpdate && (
129
129
  <span
130
130
  className="text-[9px] px-1.5 py-0.5 bg-[var(--accent)]/15 text-[var(--accent)] rounded cursor-default"
131
- title="Run: forge upgrade"
131
+ title={`forge upgrade\nnpm install -g @aion0/forge@latest`}
132
132
  >
133
133
  v{versionInfo.latest} available
134
134
  </span>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aion0/forge",
3
- "version": "0.2.23",
3
+ "version": "0.2.25",
4
4
  "description": "Unified AI workflow platform — multi-model task orchestration, persistent sessions, web terminal, remote access",
5
5
  "type": "module",
6
6
  "scripts": {