@geminilight/mindos 0.5.39 → 0.5.41

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/app/next-env.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /// <reference types="next" />
2
2
  /// <reference types="next/image-types/global" />
3
- import "./.next/types/routes.d.ts";
3
+ import "./.next/dev/types/routes.d.ts";
4
4
 
5
5
  // NOTE: This file should not be edited
6
6
  // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
package/bin/cli.js CHANGED
@@ -39,7 +39,7 @@
39
39
  */
40
40
 
41
41
  import { execSync } from 'node:child_process';
42
- import { existsSync, readFileSync, writeFileSync, rmSync, mkdirSync, cpSync } from 'node:fs';
42
+ import { existsSync, readFileSync, writeFileSync, rmSync, cpSync } from 'node:fs';
43
43
  import { resolve } from 'node:path';
44
44
  import { homedir } from 'node:os';
45
45
 
@@ -50,7 +50,7 @@ import { bold, dim, cyan, green, red, yellow } from './lib/colors.js';
50
50
  const NEXT_BIN = resolve(ROOT, 'app', 'node_modules', '.bin', 'next');
51
51
  import { run, npmInstall } from './lib/utils.js';
52
52
  import { loadConfig, getStartMode, isDaemonMode } from './lib/config.js';
53
- import { needsBuild, writeBuildStamp, clearBuildLock, cleanNextDir, ensureAppDeps } from './lib/build.js';
53
+ import { needsBuild, writeBuildStamp, cleanNextDir, ensureAppDeps } from './lib/build.js';
54
54
  import { isPortInUse, assertPortFree } from './lib/port.js';
55
55
  import { savePids, clearPids } from './lib/pid.js';
56
56
  import { stopMindos } from './lib/stop.js';
@@ -60,6 +60,72 @@ import { spawnMcp } from './lib/mcp-spawn.js';
60
60
  import { mcpInstall } from './lib/mcp-install.js';
61
61
  import { initSync, startSyncDaemon, stopSyncDaemon, getSyncStatus, manualSync, listConflicts, setSyncEnabled } from './lib/sync.js';
62
62
 
63
+ // ── Helpers ───────────────────────────────────────────────────────────────────
64
+
65
+ /**
66
+ * Dynamically resolve the new ROOT after `npm install -g`.
67
+ * This is needed because constants are evaluated at module load time.
68
+ */
69
+ function getUpdatedRoot() {
70
+ try {
71
+ const mindosBin = execSync('which mindos', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
72
+ if (mindosBin) {
73
+ // mindos bin is usually at <root>/bin/cli.js or a symlink to it
74
+ let cliPath;
75
+ try {
76
+ cliPath = execSync(`readlink -f "${mindosBin}"`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
77
+ } catch {
78
+ try {
79
+ cliPath = execSync(`realpath "${mindosBin}"`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
80
+ } catch {
81
+ cliPath = mindosBin;
82
+ }
83
+ }
84
+ if (cliPath) {
85
+ // cliPath is like /path/to/node_modules/@geminilight/mindos/bin/cli.js
86
+ // ROOT is /path/to/node_modules/@geminilight/mindos
87
+ return resolve(dirname(cliPath), '..');
88
+ }
89
+ }
90
+ } catch {}
91
+ // Fallback to static ROOT
92
+ return ROOT;
93
+ }
94
+
95
+ /**
96
+ * Build the app in the given root if the build stamp doesn't match the package version.
97
+ * Used by `mindos update` to pre-build before restarting the daemon.
98
+ */
99
+ function buildIfNeeded(newRoot) {
100
+ const newBuildStamp = resolve(newRoot, 'app', '.next', '.mindos-build-version');
101
+ const newNextBin = resolve(newRoot, 'app', 'node_modules', '.bin', 'next');
102
+
103
+ let needBuild = true;
104
+ try {
105
+ const builtVersion = readFileSync(newBuildStamp, 'utf-8').trim();
106
+ const pkgVersion = JSON.parse(readFileSync(resolve(newRoot, 'package.json'), 'utf-8')).version;
107
+ needBuild = builtVersion !== pkgVersion;
108
+ } catch {
109
+ needBuild = true;
110
+ }
111
+
112
+ if (!needBuild) return;
113
+
114
+ console.log(yellow('\n Building MindOS (version change detected)...\n'));
115
+ const appPkg = resolve(newRoot, 'app', 'package.json');
116
+ if (existsSync(appPkg)) {
117
+ run('npm install', resolve(newRoot, 'app'));
118
+ }
119
+ const nextDir = resolve(newRoot, 'app', '.next');
120
+ if (existsSync(nextDir)) {
121
+ run(`rm -rf "${nextDir}"`, newRoot);
122
+ }
123
+ run('node scripts/gen-renderer-index.js', newRoot);
124
+ run(`${newNextBin} build`, resolve(newRoot, 'app'));
125
+ const version = JSON.parse(readFileSync(resolve(newRoot, 'package.json'), 'utf-8')).version;
126
+ writeFileSync(newBuildStamp, version, 'utf-8');
127
+ }
128
+
63
129
  // ── Commands ──────────────────────────────────────────────────────────────────
64
130
 
65
131
  const cmd = process.argv[2];
@@ -665,8 +731,13 @@ ${dim('Shortcut: mindos start --daemon → install + start in one step')}
665
731
  }
666
732
 
667
733
  if (daemonRunning) {
668
- console.log(cyan('\n Daemon is running — restarting to apply the new version...'));
734
+ console.log(cyan('\n Daemon is running — stopping to apply the new version...'));
669
735
  await runGatewayCommand('stop');
736
+
737
+ // After npm install -g, resolve the new installation path and pre-build
738
+ const newRoot = getUpdatedRoot();
739
+ buildIfNeeded(newRoot);
740
+
670
741
  await runGatewayCommand('install');
671
742
  // install() starts the service:
672
743
  // - systemd: daemon-reload + enable + start
@@ -694,13 +765,16 @@ ${dim('Shortcut: mindos start --daemon → install + start in one step')}
694
765
  process.exit(1);
695
766
  }
696
767
  } else {
768
+ // Non-daemon mode: build in foreground for better UX
769
+ buildIfNeeded(getUpdatedRoot());
770
+
697
771
  console.log(`\n${green('✔')} ${bold(`Updated: ${currentVersion} → ${newVersion}`)}`);
698
- console.log(dim(' Run `mindos start` it will rebuild automatically.'));
772
+ console.log(dim(' Run `mindos start` to start the updated version.'));
699
773
  console.log(` ${dim('View changelog:')} ${cyan('https://github.com/GeminiLight/MindOS/releases')}\n`);
700
774
  }
701
775
  },
702
776
 
703
- // ── uninstall ──────────────────────────────────────────────────────────────
777
+ // ── uninstall ───────────────────────────────────────────────────────────────
704
778
  uninstall: async () => {
705
779
  const readline = await import('node:readline');
706
780
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
@@ -1,6 +1,6 @@
1
1
  import { execSync } from 'node:child_process';
2
2
  import { existsSync, readFileSync, writeFileSync, rmSync, mkdirSync, statSync, renameSync, unlinkSync, openSync, readSync, closeSync } from 'node:fs';
3
- import { resolve } from 'node:path';
3
+ import { resolve, dirname } from 'node:path';
4
4
  import { homedir } from 'node:os';
5
5
  import { MINDOS_DIR, LOG_PATH, CLI_PATH, NODE_BIN, CONFIG_PATH } from './constants.js';
6
6
  import { green, red, dim, cyan, yellow } from './colors.js';
@@ -8,6 +8,41 @@ import { isPortInUse } from './port.js';
8
8
 
9
9
  // ── Helpers ──────────────────────────────────────────────────────────────────
10
10
 
11
+ /**
12
+ * Dynamically resolve the current mindos CLI path.
13
+ * This is needed because CLI_PATH is evaluated at module load time,
14
+ * but after `npm install -g @geminilight/mindos@latest`, the path may have changed.
15
+ */
16
+ function getCurrentCliPath() {
17
+ try {
18
+ // Try to find mindos in PATH
19
+ const mindosBin = execSync('which mindos', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
20
+ if (mindosBin) {
21
+ // mindos is usually a symlink, resolve it
22
+ try {
23
+ const realPath = execSync(`readlink -f "${mindosBin}"`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
24
+ if (realPath && existsSync(realPath)) {
25
+ return realPath;
26
+ }
27
+ } catch {
28
+ // readlink -f not available on macOS, fallback to realpath
29
+ try {
30
+ const realPath = execSync(`realpath "${mindosBin}"`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
31
+ if (realPath && existsSync(realPath)) {
32
+ return realPath;
33
+ }
34
+ } catch {}
35
+ }
36
+ // Fallback: use the symlink target itself
37
+ if (existsSync(mindosBin)) {
38
+ return mindosBin;
39
+ }
40
+ }
41
+ } catch {}
42
+ // Fallback to static CLI_PATH if dynamic resolution fails
43
+ return CLI_PATH;
44
+ }
45
+
11
46
  /** Rotate log file when it exceeds 2 MB. Keeps at most one .old backup. */
12
47
  function rotateLogs() {
13
48
  try {
@@ -169,6 +204,7 @@ const systemd = {
169
204
  ensureMindosDir();
170
205
  rotateLogs();
171
206
  const currentPath = process.env.PATH ?? '/usr/local/bin:/usr/bin:/bin';
207
+ const cliPath = getCurrentCliPath();
172
208
  const unit = [
173
209
  '[Unit]',
174
210
  'Description=MindOS app + MCP server',
@@ -176,7 +212,7 @@ const systemd = {
176
212
  '',
177
213
  '[Service]',
178
214
  'Type=simple',
179
- `ExecStart=${NODE_BIN} ${CLI_PATH} start`,
215
+ `ExecStart=${NODE_BIN} ${cliPath} start`,
180
216
  'Restart=on-failure',
181
217
  'RestartSec=3',
182
218
  `Environment=HOME=${homedir()}`,
@@ -253,6 +289,7 @@ const launchd = {
253
289
  ensureMindosDir();
254
290
  rotateLogs();
255
291
  const currentPath = process.env.PATH ?? '/usr/local/bin:/usr/bin:/bin';
292
+ const cliPath = getCurrentCliPath();
256
293
  const plist = `<?xml version="1.0" encoding="UTF-8"?>
257
294
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
258
295
  <plist version="1.0">
@@ -261,7 +298,7 @@ const launchd = {
261
298
  <key>ProgramArguments</key>
262
299
  <array>
263
300
  <string>${NODE_BIN}</string>
264
- <string>${CLI_PATH}</string>
301
+ <string>${cliPath}</string>
265
302
  <string>start</string>
266
303
  </array>
267
304
  <key>RunAtLoad</key><true/>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geminilight/mindos",
3
- "version": "0.5.39",
3
+ "version": "0.5.41",
4
4
  "description": "MindOS — Human-Agent Collaborative Mind System. Local-first knowledge base that syncs your mind to all AI Agents via MCP.",
5
5
  "keywords": [
6
6
  "mindos",