@aion0/forge 0.5.16 → 0.5.18
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/.forge/mcp.json +1 -1
- package/RELEASE_NOTES.md +14 -7
- package/lib/workspace/orchestrator.ts +17 -3
- package/lib/workspace/session-monitor.ts +13 -8
- package/package.json +1 -1
package/.forge/mcp.json
CHANGED
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
# Forge v0.5.
|
|
1
|
+
# Forge v0.5.18
|
|
2
2
|
|
|
3
|
-
Released: 2026-
|
|
3
|
+
Released: 2026-04-01
|
|
4
4
|
|
|
5
|
-
## Changes since v0.5.
|
|
5
|
+
## Changes since v0.5.17
|
|
6
6
|
|
|
7
|
-
###
|
|
8
|
-
-
|
|
9
|
-
-
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
- Revert "fix: after hook done, suppress extends until file stops changing"
|
|
9
|
+
- fix: after hook done, suppress extends until file stops changing
|
|
10
|
+
- fix: warmup back to 7 polls (21s)
|
|
11
|
+
- fix: only start session monitor on new tmux creation, not existing
|
|
12
|
+
- fix: reduce warmup from 7 polls (21s) to 4 polls (12s)
|
|
13
|
+
- fix: resetState doesn't reset warmupCount, only startMonitoring does
|
|
10
14
|
|
|
15
|
+
### Other
|
|
16
|
+
- Revert "fix: after hook done, suppress extends until file stops changing"
|
|
11
17
|
|
|
12
|
-
|
|
18
|
+
|
|
19
|
+
**Full Changelog**: https://github.com/aiwatching/forge/compare/v0.5.17...v0.5.18
|
|
@@ -1633,6 +1633,8 @@ export class WorkspaceOrchestrator extends EventEmitter {
|
|
|
1633
1633
|
const entry = this.agents.get(agentId);
|
|
1634
1634
|
if (!entry) return;
|
|
1635
1635
|
entry.state.tmuxSession = undefined;
|
|
1636
|
+
// Reset session monitor warmup so it doesn't immediately trigger running on restart
|
|
1637
|
+
this.sessionMonitor?.resetState(agentId);
|
|
1636
1638
|
this.saveNow();
|
|
1637
1639
|
this.emitAgentsChanged();
|
|
1638
1640
|
}
|
|
@@ -2151,10 +2153,17 @@ export class WorkspaceOrchestrator extends EventEmitter {
|
|
|
2151
2153
|
if (supportsSession) {
|
|
2152
2154
|
let sessionId: string | undefined;
|
|
2153
2155
|
if (config.primary) {
|
|
2156
|
+
// Read fixedSessionId directly from file (avoid dynamic import issues in production build)
|
|
2154
2157
|
try {
|
|
2155
|
-
const
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
+
const psPath = join(homedir(), '.forge', 'data', 'project-sessions.json');
|
|
2159
|
+
if (existsSync(psPath)) {
|
|
2160
|
+
const psData = JSON.parse(readFileSync(psPath, 'utf-8'));
|
|
2161
|
+
sessionId = psData[this.projectPath];
|
|
2162
|
+
}
|
|
2163
|
+
console.log(`[daemon] ${config.label}: fixedSession=${sessionId || 'NONE'} for ${this.projectPath}`);
|
|
2164
|
+
} catch (err: any) {
|
|
2165
|
+
console.error(`[daemon] ${config.label}: failed to read fixedSession: ${err.message}`);
|
|
2166
|
+
}
|
|
2158
2167
|
} else {
|
|
2159
2168
|
sessionId = config.boundSessionId;
|
|
2160
2169
|
}
|
|
@@ -2255,6 +2264,11 @@ export class WorkspaceOrchestrator extends EventEmitter {
|
|
|
2255
2264
|
this.emitAgentsChanged();
|
|
2256
2265
|
}
|
|
2257
2266
|
|
|
2267
|
+
// Start session monitor only for newly created sessions (not existing ones)
|
|
2268
|
+
if (!sessionAlreadyExists) {
|
|
2269
|
+
this.startAgentSessionMonitor(agentId, config);
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2258
2272
|
// Ensure boundSessionId is set (required for session monitor + --resume)
|
|
2259
2273
|
if (!config.primary && !config.boundSessionId) {
|
|
2260
2274
|
const bindDelay = sessionAlreadyExists ? 500 : 5000;
|
|
@@ -47,6 +47,7 @@ export class SessionFileMonitor extends EventEmitter {
|
|
|
47
47
|
this.stopMonitoring(agentId);
|
|
48
48
|
this.currentState.set(agentId, 'idle');
|
|
49
49
|
this.lastStableTime.set(agentId, Date.now());
|
|
50
|
+
this.warmupCount.set(agentId, 0); // reset warmup for fresh start
|
|
50
51
|
|
|
51
52
|
const timer = setInterval(() => {
|
|
52
53
|
this.checkFile(agentId, sessionFilePath);
|
|
@@ -96,7 +97,8 @@ export class SessionFileMonitor extends EventEmitter {
|
|
|
96
97
|
resetState(agentId: string): void {
|
|
97
98
|
this.currentState.set(agentId, 'idle');
|
|
98
99
|
this.lastStableTime.set(agentId, Date.now());
|
|
99
|
-
//
|
|
100
|
+
// Don't reset warmupCount here — warmup only on startMonitoring (fresh start/restart)
|
|
101
|
+
// 10s suppress is enough to prevent immediate flip-back after hook/button
|
|
100
102
|
this.suppressUntil.set(agentId, Date.now() + 10_000);
|
|
101
103
|
}
|
|
102
104
|
|
|
@@ -110,20 +112,23 @@ export class SessionFileMonitor extends EventEmitter {
|
|
|
110
112
|
return join(homedir(), '.claude', 'projects', encoded, `${sessionId}.jsonl`);
|
|
111
113
|
}
|
|
112
114
|
|
|
113
|
-
private
|
|
115
|
+
private warmupCount = new Map<string, number>();
|
|
114
116
|
private checkFile(agentId: string, filePath: string): void {
|
|
115
117
|
try {
|
|
116
118
|
const stat = statSync(filePath);
|
|
117
119
|
const mtime = stat.mtimeMs;
|
|
118
120
|
const size = stat.size;
|
|
119
121
|
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
// Warmup: skip first 6 polls (~18s) to avoid false running during startup
|
|
123
|
+
// On poll 7 (first real check), just set new baseline — don't trigger running
|
|
124
|
+
const count = (this.warmupCount.get(agentId) || 0) + 1;
|
|
125
|
+
this.warmupCount.set(agentId, count);
|
|
126
|
+
if (count <= 7) {
|
|
123
127
|
this.lastMtime.set(agentId, mtime);
|
|
124
128
|
this.lastSize.set(agentId, size);
|
|
125
129
|
this.lastStableTime.set(agentId, Date.now());
|
|
126
|
-
console.log(`[session-monitor] ${agentId}:
|
|
130
|
+
if (count === 1) console.log(`[session-monitor] ${agentId}: warmup started`);
|
|
131
|
+
if (count === 7) console.log(`[session-monitor] ${agentId}: warmup done, monitoring active`);
|
|
127
132
|
return;
|
|
128
133
|
}
|
|
129
134
|
|
|
@@ -163,8 +168,8 @@ export class SessionFileMonitor extends EventEmitter {
|
|
|
163
168
|
}
|
|
164
169
|
}
|
|
165
170
|
} catch (err: any) {
|
|
166
|
-
if (
|
|
167
|
-
this.
|
|
171
|
+
if ((this.warmupCount.get(`err-${agentId}`) || 0) === 0) {
|
|
172
|
+
this.warmupCount.set(`err-${agentId}`, 1);
|
|
168
173
|
console.log(`[session-monitor] ${agentId}: checkFile error — ${err.message}`);
|
|
169
174
|
}
|
|
170
175
|
}
|
package/package.json
CHANGED