@mrpatronz/nexusflow 0.2.13 → 0.2.17
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/.github/dependabot.yml +52 -52
- package/.github/workflows/dependabot-merge.yml +53 -0
- package/.github/workflows/release.yml +112 -100
- package/.vscode/launch.json +17 -17
- package/.vscode/tasks.json +17 -17
- package/GETTING_STARTED.md +114 -109
- package/README.md +336 -311
- package/desktop/build-installer.js +228 -0
- package/desktop/build.js +118 -0
- package/desktop/installer/nexusflow.iss +35 -0
- package/desktop/neutralino.config.json +39 -0
- package/desktop/package-lock.json +1060 -0
- package/desktop/package.json +14 -0
- package/dist/commands/desktop.d.ts +12 -0
- package/dist/commands/desktop.d.ts.map +1 -0
- package/dist/commands/desktop.js +119 -0
- package/dist/commands/desktop.js.map +1 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +1 -3
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/tui.d.ts +8 -0
- package/dist/commands/tui.d.ts.map +1 -0
- package/dist/commands/tui.js +386 -0
- package/dist/commands/tui.js.map +1 -0
- package/dist/commands/ui.d.ts +3 -1
- package/dist/commands/ui.d.ts.map +1 -1
- package/dist/commands/ui.js +76 -19
- package/dist/commands/ui.js.map +1 -1
- package/dist/generators/base.d.ts.map +1 -1
- package/dist/generators/base.js +78 -66
- package/dist/generators/base.js.map +1 -1
- package/dist/generators/codex.js +11 -11
- package/dist/generators/copilot.js +17 -17
- package/dist/generators/cursor.js +5 -5
- package/dist/generators/index.js +50 -50
- package/dist/generators/map-generator.js +14 -14
- package/dist/generators/skills-generator.js +28 -28
- package/dist/gui/app_logo.png +0 -0
- package/dist/gui/assets/index-Ct3qq-X4.js +25 -0
- package/dist/gui/assets/index-P_ZrgHXg.css +1 -0
- package/dist/gui/icons.svg +24 -24
- package/dist/gui/index.html +18 -18
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +182 -1
- package/dist/server.js.map +1 -1
- package/dist/server.test.js +78 -0
- package/dist/server.test.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/git.d.ts +16 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +52 -0
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/multi-git.d.ts +2 -0
- package/dist/utils/multi-git.d.ts.map +1 -1
- package/dist/utils/multi-git.js +5 -2
- package/dist/utils/multi-git.js.map +1 -1
- package/dist/utils/update-check.d.ts +3 -1
- package/dist/utils/update-check.d.ts.map +1 -1
- package/dist/utils/update-check.js +23 -6
- package/dist/utils/update-check.js.map +1 -1
- package/dist/utils/workflows.d.ts +11 -0
- package/dist/utils/workflows.d.ts.map +1 -0
- package/dist/utils/workflows.js +156 -0
- package/dist/utils/workflows.js.map +1 -0
- package/dist/utils/workflows.test.d.ts +2 -0
- package/dist/utils/workflows.test.d.ts.map +1 -0
- package/dist/utils/workflows.test.js +86 -0
- package/dist/utils/workflows.test.js.map +1 -0
- package/extension/media/icon.svg +1 -0
- package/extension/package-lock.json +2673 -2811
- package/extension/package.json +108 -70
- package/extension/src/extension.ts +631 -204
- package/extension/tsconfig.json +21 -19
- package/gui/README.md +73 -73
- package/gui/e2e/wizard.spec.ts +346 -327
- package/gui/eslint.config.js +26 -26
- package/gui/index.html +17 -17
- package/gui/package-lock.json +3079 -3118
- package/gui/package.json +36 -36
- package/gui/playwright.config.ts +41 -41
- package/gui/public/app_logo.png +0 -0
- package/gui/public/icons.svg +24 -24
- package/gui/src/App.css +1 -1
- package/gui/src/App.tsx +3407 -2722
- package/gui/src/assets/vite.svg +1 -1
- package/gui/src/features/changes/ChangesViewer.tsx +388 -388
- package/gui/src/features/knowledge/KnowledgeBase.tsx +84 -84
- package/gui/src/features/onboarding/OnboardingWizard.tsx +230 -230
- package/gui/src/features/plan/ImplementationPlan.tsx +32 -32
- package/gui/src/features/services/ServiceConsole.tsx +250 -250
- package/gui/src/features/sessions/SessionHistory.tsx +195 -195
- package/gui/src/features/workspace/WorkspaceList.tsx +666 -666
- package/gui/src/index.css +152 -110
- package/gui/src/main.tsx +94 -10
- package/gui/src/types.ts +62 -62
- package/gui/tsconfig.app.json +25 -25
- package/gui/tsconfig.json +7 -7
- package/gui/tsconfig.node.json +24 -24
- package/gui/vite.config.ts +12 -12
- package/package.json +56 -56
- package/resources/workflows/plan-implement-review.md +8 -0
- package/resources/workflows/research-verify.md +6 -0
- package/resources/workflows/solo-developer.md +3 -0
- package/scripts/simulate-workspaces.ts +55 -55
- package/src/analyzers/detect-apis.ts +290 -290
- package/src/analyzers/detect-deps.ts +315 -315
- package/src/analyzers/detect-existing.ts +74 -74
- package/src/analyzers/detect-ports.ts +110 -110
- package/src/analyzers/index.ts +97 -97
- package/src/analyzers/messaging-analyzer.ts +254 -254
- package/src/analyzers/readme-summarizer.ts +102 -102
- package/src/analyzers/run-analyzer.ts +269 -269
- package/src/analyzers/tech-stack.ts +283 -283
- package/src/commands/add-repo.ts +157 -157
- package/src/commands/commands.test.ts +155 -155
- package/src/commands/commit.ts +131 -131
- package/src/commands/create.ts +207 -207
- package/src/commands/desktop.ts +128 -0
- package/src/commands/diff.ts +125 -125
- package/src/commands/doctor.ts +357 -357
- package/src/commands/handoff.ts +266 -266
- package/src/commands/init.ts +134 -134
- package/src/commands/list.ts +46 -46
- package/src/commands/logs.ts +63 -63
- package/src/commands/mcp.ts +92 -92
- package/src/commands/open.ts +129 -129
- package/src/commands/pack.ts +73 -73
- package/src/commands/refresh.ts +147 -147
- package/src/commands/remove.ts +98 -98
- package/src/commands/start.ts +117 -117
- package/src/commands/status.ts +54 -54
- package/src/commands/stop.ts +55 -55
- package/src/commands/sync.ts +151 -153
- package/src/commands/tui.ts +424 -0
- package/src/commands/ui.ts +111 -47
- package/src/core/config.test.ts +96 -96
- package/src/core/config.ts +115 -115
- package/src/core/graph.ts +344 -344
- package/src/core/packer.test.ts +99 -99
- package/src/core/packer.ts +107 -107
- package/src/core/scanner.test.ts +61 -61
- package/src/core/scanner.ts +91 -91
- package/src/core/workspace.ts +380 -380
- package/src/core/worktree.ts +120 -120
- package/src/generators/antigravity.ts +32 -32
- package/src/generators/base.ts +240 -227
- package/src/generators/claude.ts +34 -34
- package/src/generators/codex.ts +48 -48
- package/src/generators/copilot.ts +56 -56
- package/src/generators/cursor.ts +44 -44
- package/src/generators/index.ts +250 -250
- package/src/generators/map-generator.test.ts +159 -159
- package/src/generators/map-generator.ts +542 -542
- package/src/generators/plan-generator.ts +481 -481
- package/src/generators/skills-generator.ts +259 -259
- package/src/index.ts +426 -382
- package/src/mcp/server.ts +294 -294
- package/src/orchestration/detect.ts +313 -313
- package/src/orchestration/index.ts +7 -7
- package/src/orchestration/runner.ts +283 -283
- package/src/server.test.ts +555 -464
- package/src/server.ts +1308 -1104
- package/src/types.ts +408 -403
- package/src/utils/detect-ai.test.ts +44 -44
- package/src/utils/detect-ai.ts +84 -84
- package/src/utils/detect-editors.test.ts +48 -48
- package/src/utils/detect-editors.ts +57 -57
- package/src/utils/git.test.ts +74 -74
- package/src/utils/git.ts +117 -61
- package/src/utils/local-ai.test.ts +130 -130
- package/src/utils/local-ai.ts +111 -111
- package/src/utils/multi-git.ts +313 -306
- package/src/utils/prompts.ts +209 -209
- package/src/utils/session-finder.ts +483 -483
- package/src/utils/system-scanner.test.ts +89 -89
- package/src/utils/system-scanner.ts +96 -96
- package/src/utils/update-check.ts +309 -275
- package/src/utils/workflows.test.ts +114 -0
- package/src/utils/workflows.ts +178 -0
- package/tsconfig.json +19 -19
- package/vitest.config.ts +14 -14
- package/dist/gui/assets/index-CFWwqFux.js +0 -23
- package/dist/gui/assets/index-Dvc9QMvl.css +0 -2
|
@@ -1,275 +1,309 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module utils/update-check
|
|
3
|
-
* Checks for updates to the NexusFlow package on the NPM registry.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { fileURLToPath } from 'node:url';
|
|
7
|
-
import * as fs from 'node:fs';
|
|
8
|
-
import * as path from 'node:path';
|
|
9
|
-
import chalk from 'chalk';
|
|
10
|
-
|
|
11
|
-
import { loadConfig, saveConfig } from '../core/config.js';
|
|
12
|
-
|
|
13
|
-
export interface UpdateStatus {
|
|
14
|
-
currentVersion: string;
|
|
15
|
-
latestVersion: string;
|
|
16
|
-
updateAvailable: boolean;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
try {
|
|
222
|
-
const res = await execa('
|
|
223
|
-
reject: false,
|
|
224
|
-
shell: process.platform === 'win32',
|
|
225
|
-
});
|
|
226
|
-
if (res.exitCode === 0) return res.stdout.trim();
|
|
227
|
-
} catch {}
|
|
228
|
-
return '';
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @module utils/update-check
|
|
3
|
+
* Checks for updates to the NexusFlow package on the NPM registry.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import * as path from 'node:path';
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
|
|
11
|
+
import { loadConfig, saveConfig } from '../core/config.js';
|
|
12
|
+
|
|
13
|
+
export interface UpdateStatus {
|
|
14
|
+
currentVersion: string;
|
|
15
|
+
latestVersion: string;
|
|
16
|
+
updateAvailable: boolean;
|
|
17
|
+
downloadUrl?: string | null;
|
|
18
|
+
releaseNotes?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface GitHubAsset {
|
|
22
|
+
name: string;
|
|
23
|
+
browser_download_url: string;
|
|
24
|
+
size: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface GitHubRelease {
|
|
28
|
+
tag_name: string;
|
|
29
|
+
html_url: string;
|
|
30
|
+
body: string;
|
|
31
|
+
assets: GitHubAsset[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Resolves the current package version by searching for package.json upward
|
|
36
|
+
* from the directory of the executing code.
|
|
37
|
+
*/
|
|
38
|
+
export function getCurrentVersion(): string {
|
|
39
|
+
try {
|
|
40
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
41
|
+
const __dirname = path.dirname(__filename);
|
|
42
|
+
|
|
43
|
+
let currentDir = __dirname;
|
|
44
|
+
for (let i = 0; i < 5; i++) {
|
|
45
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
46
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
47
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
48
|
+
return pkg.version;
|
|
49
|
+
}
|
|
50
|
+
const parentDir = path.dirname(currentDir);
|
|
51
|
+
if (parentDir === currentDir) break;
|
|
52
|
+
currentDir = parentDir;
|
|
53
|
+
}
|
|
54
|
+
} catch {
|
|
55
|
+
// Fallback if filesystem access fails
|
|
56
|
+
}
|
|
57
|
+
return '0.1.5'; // Sensible fallback (active release)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Checks for updates from the GitHub Releases API (antan87/NexusFlow).
|
|
62
|
+
* Employs a 24-hour cache unless forced.
|
|
63
|
+
*
|
|
64
|
+
* @param force - If true, ignores the 24-hour cache and fetches immediately.
|
|
65
|
+
* @returns The update status, or null if the check fails (e.g. offline).
|
|
66
|
+
*/
|
|
67
|
+
export async function checkForUpdates(force = false): Promise<UpdateStatus | null> {
|
|
68
|
+
const currentVersion = getCurrentVersion();
|
|
69
|
+
const config = await loadConfig();
|
|
70
|
+
|
|
71
|
+
const now = Date.now();
|
|
72
|
+
const lastCheck = config.lastUpdateCheck ? new Date(config.lastUpdateCheck).getTime() : 0;
|
|
73
|
+
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
|
|
74
|
+
|
|
75
|
+
// Use cached result if within 24 hours and not forced
|
|
76
|
+
if (!force && lastCheck && (now - lastCheck < ONE_DAY_MS) && config.latestVersion) {
|
|
77
|
+
return {
|
|
78
|
+
currentVersion,
|
|
79
|
+
latestVersion: config.latestVersion,
|
|
80
|
+
updateAvailable: isNewerVersion(currentVersion, config.latestVersion),
|
|
81
|
+
downloadUrl: config.latestDownloadUrl,
|
|
82
|
+
releaseNotes: config.latestReleaseNotes,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const response = await fetch('https://api.github.com/repos/antan87/NexusFlow/releases/latest', {
|
|
88
|
+
headers: { 'User-Agent': 'NexusFlow-Updater' },
|
|
89
|
+
signal: AbortSignal.timeout(4000),
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
throw new Error(`GitHub API returned status ${response.status}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const data = await response.json() as GitHubRelease;
|
|
97
|
+
const latestVersion = data.tag_name.replace(/^v/, '');
|
|
98
|
+
|
|
99
|
+
// Resolve platform-matching asset (e.g. Setup.exe for Windows)
|
|
100
|
+
let downloadUrl: string | null = null;
|
|
101
|
+
const targetAsset = data.assets.find(asset => {
|
|
102
|
+
return asset.name.endsWith('.exe') && asset.name.toLowerCase().includes('setup');
|
|
103
|
+
});
|
|
104
|
+
if (targetAsset) {
|
|
105
|
+
downloadUrl = targetAsset.browser_download_url;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const releaseNotes = data.body || '';
|
|
109
|
+
|
|
110
|
+
// Cache results
|
|
111
|
+
config.lastUpdateCheck = new Date().toISOString();
|
|
112
|
+
config.latestVersion = latestVersion;
|
|
113
|
+
config.latestDownloadUrl = downloadUrl;
|
|
114
|
+
config.latestReleaseNotes = releaseNotes;
|
|
115
|
+
await saveConfig(config);
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
currentVersion,
|
|
119
|
+
latestVersion,
|
|
120
|
+
updateAvailable: isNewerVersion(currentVersion, latestVersion),
|
|
121
|
+
downloadUrl,
|
|
122
|
+
releaseNotes,
|
|
123
|
+
};
|
|
124
|
+
} catch {
|
|
125
|
+
// Fallback: If offline or check fails, return cached version status if available
|
|
126
|
+
if (config.latestVersion) {
|
|
127
|
+
return {
|
|
128
|
+
currentVersion,
|
|
129
|
+
latestVersion: config.latestVersion,
|
|
130
|
+
updateAvailable: isNewerVersion(currentVersion, config.latestVersion),
|
|
131
|
+
downloadUrl: config.latestDownloadUrl,
|
|
132
|
+
releaseNotes: config.latestReleaseNotes,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Simple semver comparison (checks major.minor.patch).
|
|
141
|
+
*/
|
|
142
|
+
function isNewerVersion(current: string, latest: string): boolean {
|
|
143
|
+
if (current === latest) return false;
|
|
144
|
+
|
|
145
|
+
const currentParts = current.split('.').map(Number);
|
|
146
|
+
const latestParts = latest.split('.').map(Number);
|
|
147
|
+
|
|
148
|
+
for (let i = 0; i < 3; i++) {
|
|
149
|
+
const curr = currentParts[i] || 0;
|
|
150
|
+
const lat = latestParts[i] || 0;
|
|
151
|
+
if (lat > curr) return true;
|
|
152
|
+
if (curr > lat) return false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Prints a clean, premium terminal notification banner if an update is available.
|
|
160
|
+
*/
|
|
161
|
+
export function printUpdateBanner(status: UpdateStatus): void {
|
|
162
|
+
if (!status.updateAvailable) return;
|
|
163
|
+
|
|
164
|
+
const msg = `Update available: ${chalk.red(status.currentVersion)} → ${chalk.green(status.latestVersion)}`;
|
|
165
|
+
const runMsg = `Run ${chalk.cyan('npm install -g @mrpatronz/nexusflow')} to update!`;
|
|
166
|
+
|
|
167
|
+
const cleanMsg = `Update available: ${status.currentVersion} → ${status.latestVersion}`;
|
|
168
|
+
const cleanRunMsg = `Run npm install -g @mrpatronz/nexusflow to update!`;
|
|
169
|
+
const width = Math.max(cleanMsg.length, cleanRunMsg.length) + 2;
|
|
170
|
+
|
|
171
|
+
const padMsg = ' '.repeat(width - cleanMsg.length);
|
|
172
|
+
const padRunMsg = ' '.repeat(width - cleanRunMsg.length);
|
|
173
|
+
|
|
174
|
+
const border = '─'.repeat(width);
|
|
175
|
+
console.log();
|
|
176
|
+
console.log(chalk.yellow(`┌${border}┐`));
|
|
177
|
+
console.log(chalk.yellow(`│ ${msg}${padMsg} │`));
|
|
178
|
+
console.log(chalk.yellow(`│ ${runMsg}${padRunMsg} │`));
|
|
179
|
+
console.log(chalk.yellow(`└${border}┘`));
|
|
180
|
+
console.log();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
import { execa } from 'execa';
|
|
184
|
+
|
|
185
|
+
export interface ToolUpdateStatus {
|
|
186
|
+
id: string;
|
|
187
|
+
name: string;
|
|
188
|
+
command: string;
|
|
189
|
+
installed: boolean;
|
|
190
|
+
currentVersion: string;
|
|
191
|
+
latestVersion: string;
|
|
192
|
+
updateAvailable: boolean;
|
|
193
|
+
updateCmd: string;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export async function getToolsStatus(force = false): Promise<ToolUpdateStatus[]> {
|
|
197
|
+
const currentVersion = getCurrentVersion();
|
|
198
|
+
const tools = [
|
|
199
|
+
{
|
|
200
|
+
id: 'nexusflow',
|
|
201
|
+
name: 'NexusFlow Engine',
|
|
202
|
+
command: 'nexusflow',
|
|
203
|
+
npmPackage: '@mrpatronz/nexusflow',
|
|
204
|
+
updateCmd: 'npm install -g @mrpatronz/nexusflow',
|
|
205
|
+
getCurrent: async () => currentVersion,
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
id: 'repomix',
|
|
209
|
+
name: 'Repomix (Codebase Packer)',
|
|
210
|
+
command: 'repomix',
|
|
211
|
+
npmPackage: 'repomix',
|
|
212
|
+
updateCmd: 'npm install -g repomix',
|
|
213
|
+
getCurrent: async () => {
|
|
214
|
+
try {
|
|
215
|
+
const res = await execa('repomix', ['--version'], {
|
|
216
|
+
reject: false,
|
|
217
|
+
shell: process.platform === 'win32',
|
|
218
|
+
});
|
|
219
|
+
if (res.exitCode === 0) return res.stdout.trim();
|
|
220
|
+
} catch {}
|
|
221
|
+
try {
|
|
222
|
+
const res = await execa('npx', ['repomix', '--version'], {
|
|
223
|
+
reject: false,
|
|
224
|
+
shell: process.platform === 'win32',
|
|
225
|
+
});
|
|
226
|
+
if (res.exitCode === 0) return res.stdout.trim();
|
|
227
|
+
} catch {}
|
|
228
|
+
return '';
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
id: 'antigravity',
|
|
233
|
+
name: 'Antigravity CLI',
|
|
234
|
+
command: 'agy',
|
|
235
|
+
npmPackage: '',
|
|
236
|
+
updateCmd: 'agy update',
|
|
237
|
+
getCurrent: async () => {
|
|
238
|
+
try {
|
|
239
|
+
const res = await execa('agy', ['--version'], {
|
|
240
|
+
reject: false,
|
|
241
|
+
shell: process.platform === 'win32',
|
|
242
|
+
});
|
|
243
|
+
if (res.exitCode === 0) return res.stdout.trim();
|
|
244
|
+
} catch {}
|
|
245
|
+
return '';
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
id: 'claude',
|
|
250
|
+
name: 'Claude Code CLI',
|
|
251
|
+
command: 'claude',
|
|
252
|
+
npmPackage: '@anthropic-ai/claude-code',
|
|
253
|
+
updateCmd: 'npm install -g @anthropic-ai/claude-code',
|
|
254
|
+
getCurrent: async () => {
|
|
255
|
+
try {
|
|
256
|
+
const res = await execa('claude', ['--version'], {
|
|
257
|
+
reject: false,
|
|
258
|
+
shell: process.platform === 'win32',
|
|
259
|
+
});
|
|
260
|
+
if (res.exitCode === 0) return res.stdout.trim();
|
|
261
|
+
} catch {}
|
|
262
|
+
return '';
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
];
|
|
266
|
+
|
|
267
|
+
const results: ToolUpdateStatus[] = [];
|
|
268
|
+
|
|
269
|
+
for (const t of tools) {
|
|
270
|
+
let installed = false;
|
|
271
|
+
let currentVal = '';
|
|
272
|
+
let latestVal = '';
|
|
273
|
+
|
|
274
|
+
try {
|
|
275
|
+
currentVal = await t.getCurrent();
|
|
276
|
+
installed = currentVal !== '';
|
|
277
|
+
} catch {}
|
|
278
|
+
|
|
279
|
+
if (installed && t.npmPackage) {
|
|
280
|
+
try {
|
|
281
|
+
const response = await fetch(`https://registry.npmjs.org/${t.npmPackage}/latest`, {
|
|
282
|
+
signal: AbortSignal.timeout(2000),
|
|
283
|
+
});
|
|
284
|
+
if (response.ok) {
|
|
285
|
+
const data = await response.json() as { version: string };
|
|
286
|
+
latestVal = data.version;
|
|
287
|
+
}
|
|
288
|
+
} catch {}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (!latestVal) {
|
|
292
|
+
latestVal = currentVal || '1.0.0';
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
results.push({
|
|
296
|
+
id: t.id,
|
|
297
|
+
name: t.name,
|
|
298
|
+
command: t.command,
|
|
299
|
+
installed,
|
|
300
|
+
currentVersion: currentVal || 'Not Installed',
|
|
301
|
+
latestVersion: latestVal,
|
|
302
|
+
updateAvailable: installed && isNewerVersion(currentVal, latestVal),
|
|
303
|
+
updateCmd: t.updateCmd,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return results;
|
|
308
|
+
}
|
|
309
|
+
|