@hueyexe/opencode-ensemble 0.6.4 → 0.7.0

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/src/watchdog.ts CHANGED
@@ -32,8 +32,38 @@ export class Watchdog {
32
32
  this.checkIntervalMs = opts.checkIntervalMs ?? 60_000
33
33
  }
34
34
 
35
+ private static STALE_THRESHOLD_MS = Number(process.env.STALE_WORKTREE_THRESHOLD_MS) || 300_000
36
+
37
+ /** Clean up worktrees and workspaces for shutdown/error members past the stale threshold. */
38
+ async cleanupStaleWorktrees(): Promise<void> {
39
+ const cutoff = Date.now() - Watchdog.STALE_THRESHOLD_MS
40
+ const stale = this.db.query(
41
+ `SELECT tm.team_id, tm.name, tm.worktree_dir, tm.workspace_id
42
+ FROM team_member tm
43
+ JOIN team t ON tm.team_id = t.id
44
+ WHERE t.status = 'active'
45
+ AND tm.status IN ('shutdown', 'error')
46
+ AND tm.worktree_dir IS NOT NULL
47
+ AND tm.time_updated < ?`
48
+ ).all(cutoff) as Array<{ team_id: string; name: string; worktree_dir: string; workspace_id: string | null }>
49
+
50
+ for (const m of stale) {
51
+ try {
52
+ if (m.workspace_id) {
53
+ await this.client.workspace.remove({ id: m.workspace_id })
54
+ }
55
+ await this.client.worktree.remove({ worktreeRemoveInput: { directory: m.worktree_dir } })
56
+ this.db.run(
57
+ "UPDATE team_member SET worktree_dir = NULL, worktree_branch = NULL, workspace_id = NULL WHERE team_id = ? AND name = ?",
58
+ [m.team_id, m.name]
59
+ )
60
+ } catch { /* best effort */ }
61
+ }
62
+ }
63
+
35
64
  /** Run a single check for stale busy members. */
36
65
  async check(): Promise<void> {
66
+ await this.cleanupStaleWorktrees()
37
67
  if (this.ttlMs === 0) return
38
68
 
39
69
  const cutoff = Date.now() - this.ttlMs
@@ -70,10 +100,9 @@ export class Watchdog {
70
100
  }
71
101
  }
72
102
 
73
- /** Start the periodic check. */
103
+ /** Start the periodic check. Runs stale worktree GC regardless of TTL setting. */
74
104
  start(): void {
75
105
  if (this.timer) return
76
- if (this.ttlMs === 0) return
77
106
  this.timer = setInterval(() => this.check(), this.checkIntervalMs)
78
107
  }
79
108