@aion0/forge 0.2.21 → 0.2.22

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.
@@ -12,9 +12,12 @@ const CURRENT_VERSION = (() => {
12
12
  }
13
13
  })();
14
14
 
15
- // Cache npm version check for 1 hour
15
+ // Cache npm version check for 10 minutes
16
16
  let cachedLatest: { version: string; checkedAt: number } | null = null;
17
- const CACHE_TTL = 10 * 60 * 1000; // 10 minutes
17
+ const CACHE_TTL = 10 * 60 * 1000;
18
+
19
+ // Track which versions we already notified about (avoid duplicates)
20
+ let notifiedVersion = '';
18
21
 
19
22
  async function getLatestVersion(force = false): Promise<string> {
20
23
  if (!force && cachedLatest && Date.now() - cachedLatest.checkedAt < CACHE_TTL) {
@@ -52,7 +55,20 @@ export async function GET(req: Request) {
52
55
  const force = searchParams.has('force');
53
56
  const current = CURRENT_VERSION;
54
57
  const latest = await getLatestVersion(force);
55
- const hasUpdate = latest && compareVersions(current, latest) < 0;
58
+ const hasUpdate = !!(latest && compareVersions(current, latest) < 0);
59
+
60
+ // Create a notification when new version is detected (once per version)
61
+ if (hasUpdate && latest !== notifiedVersion) {
62
+ notifiedVersion = latest;
63
+ try {
64
+ const { addNotification } = require('@/lib/notifications');
65
+ addNotification(
66
+ 'system',
67
+ `Update available: v${latest}`,
68
+ `Current: v${current}. Run: forge upgrade`,
69
+ );
70
+ } catch {}
71
+ }
56
72
 
57
73
  return NextResponse.json({
58
74
  current,
@@ -51,8 +51,6 @@ export default function Dashboard({ user }: { user: any }) {
51
51
  const [projects, setProjects] = useState<ProjectInfo[]>([]);
52
52
  const [onlineCount, setOnlineCount] = useState<{ total: number; remote: number }>({ total: 0, remote: 0 });
53
53
  const [versionInfo, setVersionInfo] = useState<{ current: string; latest: string; hasUpdate: boolean } | null>(null);
54
- const [upgrading, setUpgrading] = useState(false);
55
- const [upgradeResult, setUpgradeResult] = useState<string | null>(null);
56
54
  const [notifications, setNotifications] = useState<any[]>([]);
57
55
  const [unreadCount, setUnreadCount] = useState(0);
58
56
  const [showNotifications, setShowNotifications] = useState(false);
@@ -127,43 +125,26 @@ export default function Dashboard({ user }: { user: any }) {
127
125
  {versionInfo && (
128
126
  <span className="flex items-center gap-1.5">
129
127
  <span className="text-[10px] text-[var(--text-secondary)]">v{versionInfo.current}</span>
130
- {versionInfo.hasUpdate && !upgradeResult && (
131
- <button
132
- disabled={upgrading}
133
- onClick={async () => {
134
- setUpgrading(true);
135
- try {
136
- const res = await fetch('/api/upgrade', { method: 'POST' });
137
- const data = await res.json();
138
- setUpgradeResult(data.ok ? data.message : data.error);
139
- if (data.ok) setVersionInfo(v => v ? { ...v, hasUpdate: false } : v);
140
- } catch { setUpgradeResult('Upgrade failed'); }
141
- setUpgrading(false);
142
- }}
143
- className="text-[9px] px-1.5 py-0.5 bg-[var(--accent)] text-white rounded hover:opacity-90 disabled:opacity-50"
144
- title={`Update to v${versionInfo.latest}\nOr run: forge upgrade`}
128
+ {versionInfo.hasUpdate && (
129
+ <span
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"
145
132
  >
146
- {upgrading ? 'Upgrading...' : `Update v${versionInfo.latest}`}
147
- </button>
148
- )}
149
- {!versionInfo.hasUpdate && !upgradeResult && (
150
- <button
151
- onClick={async () => {
152
- const res = await fetch('/api/version?force=1');
153
- const data = await res.json();
154
- setVersionInfo(data);
155
- }}
156
- className="text-[9px] px-1 py-0.5 text-[var(--text-secondary)] hover:text-[var(--text-primary)]"
157
- title="Check for updates"
158
- >
159
-
160
- </button>
161
- )}
162
- {upgradeResult && (
163
- <span className="text-[9px] text-[var(--green)] max-w-[200px] truncate" title={upgradeResult}>
164
- {upgradeResult}
133
+ v{versionInfo.latest} available
165
134
  </span>
166
135
  )}
136
+ <button
137
+ onClick={async () => {
138
+ const res = await fetch('/api/version?force=1');
139
+ const data = await res.json();
140
+ setVersionInfo(data);
141
+ if (data.hasUpdate) fetchNotifications();
142
+ }}
143
+ className="text-[9px] px-1 py-0.5 text-[var(--text-secondary)] hover:text-[var(--text-primary)]"
144
+ title="Check for updates"
145
+ >
146
+
147
+ </button>
167
148
  </span>
168
149
  )}
169
150
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aion0/forge",
3
- "version": "0.2.21",
3
+ "version": "0.2.22",
4
4
  "description": "Unified AI workflow platform — multi-model task orchestration, persistent sessions, web terminal, remote access",
5
5
  "type": "module",
6
6
  "scripts": {