Skip to content

Commit aceaa40

Browse files
author
Tajudeen
committed
feat: add update notification system similar to Cursor
- Add post-install/update notification system that shows when version changes - Update all GitHub URLs to use opencortexide organization - Add releaseNotesUrl to product.json - Track last seen version in storage to detect new installations/updates - Show welcome message for new installations and update notifications - Link to GitHub releases for 'What's New' feature
1 parent 28c79a4 commit aceaa40

File tree

5 files changed

+157
-6
lines changed

5 files changed

+157
-6
lines changed

extensions/open-remote-ssh/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
"type": "string",
7373
"description": "The URL from where the vscode server will be downloaded. You can use the following variables and they will be replaced dynamically:\n- ${quality}: vscode server quality, e.g. stable or insiders\n- ${version}: vscode server version, e.g. 1.69.0\n- ${commit}: vscode server release commit\n- ${arch}: vscode server arch, e.g. x64, armhf, arm64\n- ${release}: release number",
7474
"scope": "application",
75-
"default": "https://github.com/cortexide/cortexide/releases/download/${version}/cortexide-reh-${os}-${arch}-${version}.tar.gz"
75+
"default": "https://github.com/opencortexide/cortexide/releases/download/${version}/cortexide-reh-${os}-${arch}-${version}.tar.gz"
7676
},
7777
"remote.SSH.remotePlatform": {
7878
"type": "object",

product.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
"dataFolderName": ".cortexide",
88
"win32MutexName": "cortexide",
99
"licenseName": "MIT",
10-
"licenseUrl": "https://github.com/cortexide/cortexide/blob/main/LICENSE.txt",
11-
"serverLicenseUrl": "https://github.com/cortexide/cortexide/blob/main/LICENSE.txt",
10+
"licenseUrl": "https://github.com/opencortexide/cortexide/blob/main/LICENSE.txt",
11+
"serverLicenseUrl": "https://github.com/opencortexide/cortexide/blob/main/LICENSE.txt",
1212
"serverGreeting": [],
1313
"serverLicense": [],
1414
"serverLicensePrompt": "",
@@ -29,7 +29,8 @@
2929
"darwinBundleIdentifier": "com.cortexide.code",
3030
"linuxIconName": "cortexide",
3131
"licenseFileName": "LICENSE.txt",
32-
"reportIssueUrl": "https://github.com/cortexide/cortexide/issues/new",
32+
"reportIssueUrl": "https://github.com/opencortexide/cortexide/issues/new",
33+
"releaseNotesUrl": "https://github.com/opencortexide/cortexide/releases",
3334
"nodejsRepository": "https://nodejs.org",
3435
"urlProtocol": "cortexide",
3536
"extensionsGallery": {
@@ -39,7 +40,7 @@
3940
"builtInExtensions": [],
4041
"linkProtectionTrustedDomains": [
4142
"https://opencortexide.com",
42-
"https://github.com/cortexide/cortexide",
43+
"https://github.com/opencortexide/cortexide",
4344
"https://ollama.com"
4445
]
4546
,

src/vs/workbench/contrib/cortexide/browser/cortexide.contribution.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import './media/cortexide.css'
3333

3434
// update (frontend part, also see platform/)
3535
import './cortexideUpdateActions.js'
36+
import './cortexideUpdateNotification.js'
3637

3738
import './convertToLLMMessageWorkbenchContrib.js'
3839

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*--------------------------------------------------------------------------------------
2+
* Copyright 2025 Glass Devtools, Inc. All rights reserved.
3+
* Licensed under the Apache License, Version 2.0. See LICENSE.txt for more information.
4+
*--------------------------------------------------------------------------------------*/
5+
6+
import { Disposable } from '../../../../base/common/lifecycle.js';
7+
import Severity from '../../../../base/common/severity.js';
8+
import { IWorkbenchContribution, registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js';
9+
import { INotificationService, INotificationActions } from '../../../../platform/notification/common/notification.js';
10+
import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';
11+
import { IProductService } from '../../../../platform/product/common/productService.js';
12+
import { IHostService } from '../../../../platform/host/browser/host.js';
13+
import { IOpenerService } from '../../../../platform/opener/common/opener.js';
14+
import { URI } from '../../../../base/common/uri.js';
15+
import { IAction } from '../../../../base/common/actions.js';
16+
import { localize2 } from '../../../../nls.js';
17+
18+
const LAST_SEEN_VERSION_KEY = 'cortexide.update.lastSeenVersion';
19+
const UPDATE_NOTIFICATION_DISMISSED_KEY = 'cortexide.update.notificationDismissed';
20+
21+
/**
22+
* Shows a notification when a new version is detected after installation or update.
23+
* Similar to Cursor's update notification system.
24+
*/
25+
class CortexideUpdateNotificationContribution extends Disposable implements IWorkbenchContribution {
26+
static readonly ID = 'workbench.contrib.cortexide.updateNotification';
27+
28+
constructor(
29+
@IStorageService private readonly _storageService: IStorageService,
30+
@IProductService private readonly _productService: IProductService,
31+
@INotificationService private readonly _notificationService: INotificationService,
32+
@IHostService private readonly _hostService: IHostService,
33+
@IOpenerService private readonly _openerService: IOpenerService,
34+
) {
35+
super();
36+
37+
// Wait for the window to have focus before showing the notification
38+
this._hostService.hadLastFocus().then(async hadLastFocus => {
39+
if (!hadLastFocus) {
40+
return;
41+
}
42+
43+
// Small delay to ensure the UI is fully loaded
44+
await new Promise(resolve => setTimeout(resolve, 2000));
45+
46+
this._checkAndShowUpdateNotification();
47+
});
48+
}
49+
50+
private _checkAndShowUpdateNotification(): void {
51+
const currentVersion = this._productService.version;
52+
const lastSeenVersion = this._storageService.get(LAST_SEEN_VERSION_KEY, StorageScope.APPLICATION, '');
53+
54+
// If this is the first time running or version has changed
55+
if (!lastSeenVersion || lastSeenVersion !== currentVersion) {
56+
// Check if user has already dismissed the notification for this version
57+
const dismissedVersion = this._storageService.get(UPDATE_NOTIFICATION_DISMISSED_KEY, StorageScope.APPLICATION, '');
58+
59+
if (dismissedVersion !== currentVersion) {
60+
const isNewInstallation = !lastSeenVersion;
61+
this._showUpdateNotification(currentVersion, isNewInstallation);
62+
}
63+
64+
// Update the last seen version
65+
this._storageService.store(LAST_SEEN_VERSION_KEY, currentVersion, StorageScope.APPLICATION, StorageTarget.MACHINE);
66+
}
67+
}
68+
69+
private _showUpdateNotification(version: string, isNewInstallation: boolean): void {
70+
const message = isNewInstallation
71+
? localize2('updateNotification.welcome', 'Welcome to {0} {1}!', this._productService.nameLong, version)
72+
: localize2('updateNotification.updated', '{0} has been updated to {1}!', this._productService.nameLong, version);
73+
74+
const primaryActions: IAction[] = [];
75+
76+
// Add "What's New" button if release notes URL is available
77+
if (this._productService.releaseNotesUrl) {
78+
primaryActions.push({
79+
id: 'cortexide.update.whatsNew',
80+
label: localize2('updateNotification.whatsNew', 'What\'s New'),
81+
enabled: true,
82+
tooltip: localize2('updateNotification.whatsNewTooltip', 'View release notes'),
83+
class: undefined,
84+
run: async () => {
85+
const uri = URI.parse(this._productService.releaseNotesUrl!);
86+
await this._openerService.open(uri);
87+
}
88+
});
89+
} else {
90+
// Fallback to GitHub releases if no release notes URL is configured
91+
primaryActions.push({
92+
id: 'cortexide.update.whatsNew',
93+
label: localize2('updateNotification.whatsNew', 'What\'s New'),
94+
enabled: true,
95+
tooltip: localize2('updateNotification.whatsNewTooltip', 'View release notes'),
96+
class: undefined,
97+
run: async () => {
98+
const uri = URI.parse('https://github.com/opencortexide/cortexide/releases');
99+
await this._openerService.open(uri);
100+
}
101+
});
102+
}
103+
104+
// Add dismiss button
105+
const notificationHandle = this._notificationService.notify({
106+
severity: Severity.Info,
107+
message: message,
108+
actions: {
109+
primary: primaryActions,
110+
secondary: [
111+
{
112+
id: 'cortexide.update.dismiss',
113+
label: localize2('updateNotification.dismiss', 'Dismiss'),
114+
enabled: true,
115+
tooltip: localize2('updateNotification.dismissTooltip', 'Dismiss this notification'),
116+
class: undefined,
117+
run: () => {
118+
// Mark this version as dismissed
119+
this._storageService.store(
120+
UPDATE_NOTIFICATION_DISMISSED_KEY,
121+
version,
122+
StorageScope.APPLICATION,
123+
StorageTarget.USER
124+
);
125+
notificationHandle.close();
126+
}
127+
}
128+
]
129+
},
130+
sticky: isNewInstallation, // Sticky for new installations, auto-dismiss for updates
131+
});
132+
133+
// Auto-dismiss after 30 seconds if it's not a new installation
134+
if (!isNewInstallation) {
135+
setTimeout(() => {
136+
if (!notificationHandle.isDisposed) {
137+
notificationHandle.close();
138+
}
139+
}, 30000);
140+
}
141+
}
142+
}
143+
144+
registerWorkbenchContribution2(
145+
CortexideUpdateNotificationContribution.ID,
146+
CortexideUpdateNotificationContribution,
147+
WorkbenchPhase.Eventually
148+
);
149+

src/vs/workbench/contrib/cortexide/browser/react/src/void-settings-tsx/Settings.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ const SimpleModelSettingsDialog = ({
350350
onClose();
351351
};
352352

353-
const sourcecodeOverridesLink = `https://github.com/cortexide/cortexide/blob/main/src/vs/workbench/contrib/cortexide/common/modelCapabilities.ts#L146-L172`
353+
const sourcecodeOverridesLink = `https://github.com/opencortexide/cortexide/blob/main/src/vs/workbench/contrib/cortexide/common/modelCapabilities.ts#L146-L172`
354354

355355
return (
356356
<div // Backdrop

0 commit comments

Comments
 (0)