@aion0/forge 0.4.12 → 0.4.14

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/RELEASE_NOTES.md CHANGED
@@ -1,14 +1,18 @@
1
- # Forge v0.4.12
1
+ # Forge v0.4.14
2
2
 
3
3
  Released: 2026-03-23
4
4
 
5
- ## Changes since v0.4.11
5
+ ## Changes since v0.4.13
6
6
 
7
- ### Features
8
- - feat: terminal bell notification + Java/Scala file support
7
+ ### Bug Fixes
8
+ - fix: bell idle timer 10s + 90s fallback
9
+ - fix: bell uses idle detection instead of output pattern matching
10
+ - fix: bell resets only on Enter key, not every keystroke
11
+ - fix: bell cooldown 2min per tab label, prevents duplicate notifications
12
+ - fix: bell requires 2000+ bytes of new output before checking markers
13
+ - fix: notification timestamps display in correct timezone
14
+ - fix: bell fires once per claude task, suppressed on attach/redraw
15
+ - fix: bell detects claude completion markers (Cogitated, tokens, prompt)
9
16
 
10
- ### Other
11
- - support more dev language
12
17
 
13
-
14
- **Full Changelog**: https://github.com/aiwatching/forge/compare/v0.4.11...v0.4.12
18
+ **Full Changelog**: https://github.com/aiwatching/forge/compare/v0.4.13...v0.4.14
@@ -168,16 +168,15 @@ const pendingCommands = new Map<number, string>();
168
168
 
169
169
  const bellEnabledPanes = new Set<number>();
170
170
  const bellPaneLabels = new Map<number, string>();
171
- const bellLastFired = new Map<number, number>(); // paneId -> timestamp
172
- const BELL_COOLDOWN = 30000; // 30s cooldown between bells
171
+ const bellLastFired = new Map<string, number>(); // tabLabel -> timestamp
172
+ const BELL_COOLDOWN = 120000; // 2min cooldown between bells
173
173
 
174
174
  function fireBellNotification(paneId: number) {
175
+ const label = bellPaneLabels.get(paneId) || 'Terminal';
175
176
  const now = Date.now();
176
- const last = bellLastFired.get(paneId) || 0;
177
+ const last = bellLastFired.get(label) || 0;
177
178
  if (now - last < BELL_COOLDOWN) return;
178
- bellLastFired.set(paneId, now);
179
-
180
- const label = bellPaneLabels.get(paneId) || 'Terminal';
179
+ bellLastFired.set(label, now);
181
180
 
182
181
  // Browser notification
183
182
  if (typeof Notification !== 'undefined' && Notification.permission === 'granted') {
@@ -1120,8 +1119,10 @@ const MemoTerminalPane = memo(function TerminalPane({
1120
1119
  if (!containerRef.current) return;
1121
1120
 
1122
1121
  let disposed = false; // guard against post-cleanup writes (React Strict Mode)
1122
+ let bellArmed = false; // armed after user presses Enter
1123
+ let bellNewBytes = 0;
1123
1124
  let bellIdleTimer = 0;
1124
- let bellActivityBytes = 0;
1125
+ let bellArmedAt = 0; // timestamp when armed
1125
1126
 
1126
1127
  // Read terminal theme from CSS variables
1127
1128
  const cs = getComputedStyle(document.documentElement);
@@ -1258,14 +1259,24 @@ const MemoTerminalPane = memo(function TerminalPane({
1258
1259
  const msg = JSON.parse(event.data);
1259
1260
  if (msg.type === 'output') {
1260
1261
  try { term.write(msg.data); } catch {};
1261
- // Bell idle detection
1262
- bellActivityBytes += (msg.data as string).length;
1263
- clearTimeout(bellIdleTimer);
1264
- if (bellActivityBytes >= 200 && bellEnabledPanes.has(id)) {
1265
- bellIdleTimer = window.setTimeout(() => {
1266
- bellActivityBytes = 0;
1267
- fireBellNotification(id);
1268
- }, 8000);
1262
+ // Bell: detect claude completion
1263
+ // Bell: idle detection after user submits prompt
1264
+ if (bellEnabledPanes.has(id) && bellArmed) {
1265
+ bellNewBytes += (msg.data as string).length;
1266
+ clearTimeout(bellIdleTimer);
1267
+ if (bellNewBytes > 2000) {
1268
+ // 10s idle = claude finished
1269
+ bellIdleTimer = window.setTimeout(() => {
1270
+ bellArmed = false;
1271
+ fireBellNotification(id);
1272
+ }, 10000);
1273
+ // Fallback: if 90s since armed with activity, force fire
1274
+ if (Date.now() - bellArmedAt > 90000) {
1275
+ bellArmed = false;
1276
+ clearTimeout(bellIdleTimer);
1277
+ fireBellNotification(id);
1278
+ }
1279
+ }
1269
1280
  }
1270
1281
  } else if (msg.type === 'connected') {
1271
1282
  connectedSession = msg.sessionName;
@@ -1357,6 +1368,13 @@ const MemoTerminalPane = memo(function TerminalPane({
1357
1368
 
1358
1369
  term.onData((data) => {
1359
1370
  if (ws?.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'input', data }));
1371
+ // Arm bell on Enter (user submitted a new prompt)
1372
+ if (data === '\r' || data === '\n') {
1373
+ bellArmed = true;
1374
+ bellNewBytes = 0;
1375
+ bellArmedAt = Date.now();
1376
+ clearTimeout(bellIdleTimer);
1377
+ }
1360
1378
  });
1361
1379
 
1362
1380
  // ── Resize handling ──
@@ -1415,7 +1433,6 @@ const MemoTerminalPane = memo(function TerminalPane({
1415
1433
  visObserver.disconnect();
1416
1434
  clearTimeout(resizeTimer);
1417
1435
  clearTimeout(reconnectTimer);
1418
- clearTimeout(bellIdleTimer);
1419
1436
  window.removeEventListener('terminal-drag-end', onDragEnd);
1420
1437
  resizeObserver.disconnect();
1421
1438
  // Strict Mode cleanup: if disposed within 2s of mount and we created a
package/forge-logo.svg ADDED
@@ -0,0 +1,106 @@
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
3
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
4
+ <svg version="1.0" xmlns="http://www.w3.org/2000/svg"
5
+ width="1050.000000pt" height="1102.000000pt" viewBox="0 0 1050.000000 1102.000000"
6
+ preserveAspectRatio="xMidYMid meet">
7
+
8
+ <g transform="translate(0.000000,1102.000000) scale(0.100000,-0.100000)"
9
+ fill="#000000" stroke="none">
10
+ <path d="M0 5510 l0 -5510 5250 0 5250 0 0 5510 0 5510 -5250 0 -5250 0 0
11
+ -5510z m2410 3369 c37 -18 164 -120 395 -319 584 -503 1025 -883 1101 -946 39
12
+ -34 111 -96 159 -138 52 -45 96 -76 109 -76 12 0 233 45 492 99 258 55 503
13
+ 106 544 115 67 13 83 14 137 1 74 -17 147 -33 398 -85 105 -21 233 -48 285
14
+ -60 237 -52 327 -70 350 -70 25 0 127 84 655 541 61 52 162 139 225 193 63 54
15
+ 171 147 240 207 475 410 597 512 643 536 74 38 198 44 279 13 66 -24 145 -92
16
+ 181 -153 60 -101 57 -27 57 -1656 l0 -1492 54 -217 c57 -224 150 -590 185
17
+ -722 10 -41 38 -147 62 -235 23 -88 47 -185 54 -215 7 -30 16 -67 20 -82 6
18
+ -25 5 -28 -19 -28 -15 0 -29 6 -32 14 -4 11 -13 12 -35 6 -16 -5 -68 -12 -114
19
+ -15 l-84 -7 -6 29 c-4 15 -9 35 -12 43 -2 8 -29 110 -58 225 -30 116 -75 289
20
+ -100 385 -25 96 -81 316 -125 488 l-80 313 0 1495 c0 1664 5 1554 -65 1554
21
+ -29 0 -49 -13 -123 -77 -88 -77 -479 -412 -617 -528 -40 -33 -213 -181 -385
22
+ -330 -173 -148 -399 -343 -504 -432 -121 -105 -197 -163 -211 -163 -21 0 -115
23
+ 19 -525 106 -204 43 -302 64 -500 105 l-155 32 -115 -23 c-63 -12 -155 -31
24
+ -205 -42 -49 -11 -133 -28 -185 -39 -52 -11 -124 -27 -160 -34 -259 -56 -505
25
+ -105 -526 -105 -17 0 -66 36 -162 119 -341 296 -862 743 -1486 1275 -166 142
26
+ -194 156 -230 120 -9 -8 -17 -16 -18 -17 -2 -1 -5 -688 -8 -1527 l-5 -1525
27
+ -53 -195 c-28 -107 -79 -298 -111 -425 -33 -126 -72 -275 -86 -330 -15 -55
28
+ -46 -177 -70 -271 -64 -248 -50 -226 -142 -219 -129 10 -144 11 -149 3 -8 -13
29
+ -54 -9 -54 5 0 6 5 28 11 47 6 19 17 60 24 90 11 50 115 454 165 645 12 44 56
30
+ 213 98 375 l77 295 5 1540 5 1540 33 67 c40 81 117 155 193 186 78 31 202 27
31
+ 279 -9z m560 -1324 c0 -85 0 -85 -26 -85 -36 0 -81 -29 -94 -59 -6 -14 -14
32
+ -112 -19 -217 -9 -212 -21 -257 -83 -309 l-30 -25 40 -44 c58 -63 73 -120 78
33
+ -301 2 -82 4 -160 4 -173 0 -37 52 -82 94 -82 l36 0 0 -85 0 -85 -47 0 c-107
34
+ 1 -190 39 -237 111 -42 63 -56 137 -56 294 0 77 -3 157 -6 177 -9 50 -43 85
35
+ -98 100 l-46 12 0 78 c0 77 0 78 28 84 111 24 115 34 123 268 6 204 13 236 58
36
+ 307 45 72 133 113 254 118 l27 1 0 -85z m4810 42 c117 -58 150 -147 150 -406
37
+ 0 -192 17 -229 113 -246 l38 -7 -3 -76 -3 -75 -49 -17 c-84 -28 -89 -41 -97
38
+ -254 -4 -101 -10 -199 -14 -218 -17 -79 -79 -154 -153 -185 -19 -8 -66 -15
39
+ -106 -16 l-71 -2 0 80 0 79 45 8 c81 13 86 27 93 239 7 208 18 258 73 316 19
40
+ 20 34 37 34 38 0 1 -16 19 -35 40 -52 57 -65 109 -66 254 0 196 -10 259 -43
41
+ 287 -15 13 -45 27 -67 30 l-39 7 0 77 c0 54 4 80 13 83 32 12 126 -6 187 -36z
42
+ m-3638 -2314 c233 -236 490 -501 596 -615 72 -77 72 -77 72 -133 l0 -57 -177
43
+ -181 c-455 -467 -688 -697 -710 -697 -23 0 -198 181 -198 206 0 7 159 173 354
44
+ 369 195 195 353 357 350 360 -17 18 -186 194 -424 438 -154 159 -282 293 -284
45
+ 299 -3 10 197 218 210 218 3 0 98 -93 211 -207z m2473 -1633 l0 -145 -95 -6
46
+ c-121 -9 -1077 -8 -1320 0 l-185 6 -3 134 c-2 90 1 138 9 147 10 12 136 14
47
+ 803 12 l791 -3 0 -145z m-4912 -141 c21 -35 42 -73 48 -84 22 -47 71 -129 86
48
+ -143 14 -14 16 -14 25 1 5 9 14 17 20 17 7 0 6 -5 -2 -15 -6 -8 -9 -19 -5 -26
49
+ 4 -6 2 -15 -5 -19 -9 -5 -5 -20 13 -56 13 -27 28 -59 32 -72 4 -13 25 -55 47
50
+ -93 38 -65 44 -106 16 -97 -11 4 -40 53 -160 278 -66 123 -173 337 -188 374
51
+ -10 28 -10 29 12 14 13 -9 40 -44 61 -79z m7221 54 c-4 -16 -28 -68 -54 -118
52
+ -26 -49 -80 -153 -120 -230 -40 -77 -90 -170 -112 -207 -21 -36 -38 -71 -38
53
+ -77 0 -13 -27 -15 -34 -2 -3 5 8 41 24 79 17 39 30 78 30 87 0 9 5 13 11 9 8
54
+ -4 9 1 4 17 -4 13 -4 21 0 17 5 -4 14 0 21 10 9 13 10 20 1 31 -10 12 -9 14 4
55
+ 9 17 -7 40 30 132 212 74 146 149 240 131 163z m-284 -35 c-7 -18 -33 -75 -57
56
+ -126 -24 -51 -43 -99 -43 -106 0 -7 -7 -19 -15 -26 -9 -7 -13 -20 -10 -30 3
57
+ -10 -5 -26 -21 -41 -14 -13 -46 -59 -71 -101 -30 -53 -49 -75 -59 -71 -8 3
58
+ -14 9 -14 13 0 28 233 461 252 468 4 2 8 8 8 13 0 11 33 47 39 43 2 -2 -2 -18
59
+ -9 -36z m-6543 -260 c99 -190 119 -235 106 -241 -18 -11 -8 -24 -87 113 -87
60
+ 148 -108 179 -124 180 -14 0 -36 49 -27 58 3 4 8 -4 12 -16 3 -12 10 -22 15
61
+ -22 5 0 0 17 -11 38 -28 52 -51 111 -51 132 0 10 -5 20 -12 22 -7 3 -8 9 -3
62
+ 18 15 24 52 -34 182 -282z m-231 54 c-18 -18 -29 -12 -20 11 3 9 12 13 21 10
63
+ 13 -5 13 -8 -1 -21z m6779 -162 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2
64
+ 10 4 10 3 0 8 -4 11 -10z m-751 -568 c-22 -19 -66 -52 -99 -75 -33 -22 -99
65
+ -69 -146 -103 -48 -35 -89 -64 -93 -64 -3 0 -14 -7 -23 -16 -17 -14 -69 -51
66
+ -248 -174 -36 -25 -107 -74 -158 -110 -51 -36 -100 -69 -109 -75 -8 -5 -43
67
+ -30 -78 -55 -34 -25 -75 -53 -92 -62 -17 -9 -34 -21 -37 -25 -15 -20 -72 -53
68
+ -82 -47 -12 7 48 63 69 64 6 0 12 4 12 8 0 5 33 31 72 58 40 27 77 53 83 57
69
+ 16 12 252 181 414 295 73 52 180 126 205 142 27 17 67 46 204 147 62 45 106
70
+ 71 121 70 22 -1 21 -4 -15 -35z m-5149 -18 c5 -5 30 -23 54 -39 25 -15 50 -32
71
+ 55 -37 6 -5 65 -47 131 -93 66 -46 125 -88 130 -92 6 -4 30 -21 55 -37 25 -16
72
+ 72 -50 105 -75 58 -45 100 -75 134 -96 9 -5 32 -22 51 -37 20 -14 71 -50 115
73
+ -79 44 -29 97 -71 119 -93 21 -21 36 -34 32 -28 -12 20 10 13 36 -10 14 -13
74
+ 35 -30 47 -38 11 -8 21 -20 21 -28 0 -12 -27 2 -75 40 -5 5 -53 37 -105 71
75
+ -134 89 -261 177 -285 197 -11 10 -74 54 -140 99 -66 45 -147 102 -180 126
76
+ -70 52 -161 116 -183 130 -12 7 -140 100 -181 131 -1 1 0 7 3 13 7 11 39 -2
77
+ 61 -25z m5388 -81 c-5 -12 -3 -14 8 -8 68 39 -178 -142 -435 -320 -154 -106
78
+ -291 -203 -384 -270 -53 -39 -135 -96 -182 -127 -102 -69 -351 -246 -383 -273
79
+ -52 -44 -168 -104 -167 -88 1 11 75 67 195 148 96 65 153 106 288 206 34 25
80
+ 107 76 162 114 93 63 384 273 467 337 20 15 39 28 43 28 3 0 45 29 93 64 78
81
+ 57 294 206 299 206 1 0 -1 -7 -4 -17z m-5615 -47 c71 -47 139 -94 159 -111 6
82
+ -5 49 -36 95 -68 46 -32 162 -114 258 -183 96 -69 231 -164 300 -211 122 -85
83
+ 260 -185 290 -210 8 -7 24 -19 35 -27 11 -8 17 -17 13 -21 -7 -8 -42 10 -84
84
+ 42 -16 12 -76 54 -134 93 -58 39 -143 98 -190 131 -47 33 -96 68 -110 77 -26
85
+ 17 -177 125 -195 139 -5 4 -30 21 -55 38 -25 16 -95 66 -156 111 -61 45 -122
86
+ 87 -135 94 -25 14 -113 79 -140 105 -9 8 -20 15 -26 15 -5 0 -10 7 -10 15 0
87
+ 23 13 19 85 -29z m1347 -667 c11 -17 -1 -21 -15 -4 -8 9 -8 15 -2 15 6 0 14
88
+ -5 17 -11z m2850 1 c10 -16 -258 -206 -276 -195 -15 10 0 25 19 18 9 -3 14 -3
89
+ 10 2 -9 9 26 42 53 50 11 4 19 11 19 17 0 6 3 8 7 5 3 -4 16 5 29 18 13 14 27
90
+ 25 31 26 4 0 28 15 53 34 53 40 47 37 55 25z m-2795 -49 c-1 -15 -2 -15 -13 0
91
+ -7 9 -19 14 -27 12 -13 -4 -13 -3 -1 5 19 13 41 4 41 -17z m178 -117 c34 -27
92
+ 37 -39 8 -28 -9 3 -14 10 -11 14 3 4 -8 10 -23 13 -15 4 -40 19 -57 34 -16 15
93
+ -43 35 -58 43 -16 8 -24 16 -18 18 6 2 8 8 5 14 -7 11 99 -63 154 -108z m-190
94
+ -152 c62 -43 76 -62 47 -62 -8 0 -15 3 -15 8 0 4 -15 13 -32 21 -18 8 -35 17
95
+ -38 20 -3 3 -27 22 -55 40 -27 19 -52 37 -55 41 -3 3 -24 18 -47 33 -25 18
96
+ -40 34 -36 43 5 13 36 -6 231 -144z m452 28 c0 -5 -15 -10 -34 -10 -19 0 -38
97
+ 5 -41 10 -4 6 10 10 34 10 23 0 41 -4 41 -10z m685 5 c-25 -8 -675 -12 -675
98
+ -4 0 5 141 9 343 8 188 0 338 -2 332 -4z m705 -5 c-96 -3 -249 -3 -340 0 -113
99
+ 4 -58 6 175 6 246 0 291 -2 165 -6z m263 3 c-7 -2 -21 -2 -30 0 -10 3 -4 5 12
100
+ 5 17 0 24 -2 18 -5z m165 0 c-21 -2 -57 -2 -80 0 -24 2 -7 4 37 4 44 0 63 -2
101
+ 43 -4z m401 -119 c-6 -7 -15 -12 -19 -9 -5 3 -11 1 -15 -5 -4 -6 -11 -7 -17
102
+ -4 -5 4 2 14 18 25 30 20 52 15 33 -7z m-134 -84 c3 -5 -3 -10 -15 -10 -12 0
103
+ -18 5 -15 10 3 6 10 10 15 10 5 0 12 -4 15 -10z m-71 -39 c3 -5 -11 -7 -32 -4
104
+ -49 7 -54 13 -9 13 20 0 38 -4 41 -9z"/>
105
+ </g>
106
+ </svg>
@@ -40,7 +40,7 @@ export function getNotifications(limit = 50, offset = 0): Notification[] {
40
40
  body: r.body,
41
41
  read: !!r.read,
42
42
  taskId: r.task_id,
43
- createdAt: r.created_at,
43
+ createdAt: r.created_at ? (r.created_at.endsWith('Z') ? r.created_at : r.created_at.replace(' ', 'T') + 'Z') : r.created_at,
44
44
  }));
45
45
  }
46
46
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aion0/forge",
3
- "version": "0.4.12",
3
+ "version": "0.4.14",
4
4
  "description": "Unified AI workflow platform — multi-model task orchestration, persistent sessions, web terminal, remote access",
5
5
  "type": "module",
6
6
  "scripts": {