@prevalentware/opencode-goal-plugin 0.1.21 → 0.1.23

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/dist/server.js CHANGED
@@ -1144,7 +1144,7 @@ class TaskTracker {
1144
1144
  }
1145
1145
  async refreshLiveChildren(client, parentSessionID) {
1146
1146
  const session = client.session;
1147
- if (!session.children || !session.status)
1147
+ if (!session.children)
1148
1148
  return;
1149
1149
  let childIDs;
1150
1150
  try {
@@ -1154,7 +1154,8 @@ class TaskTracker {
1154
1154
  } catch {
1155
1155
  return;
1156
1156
  }
1157
- if (childIDs.length === 0)
1157
+ this.markAbsentRunningChildren(parentSessionID, new Set(childIDs));
1158
+ if (childIDs.length === 0 || !session.status)
1158
1159
  return;
1159
1160
  let statuses;
1160
1161
  try {
@@ -1240,6 +1241,16 @@ class TaskTracker {
1240
1241
  continue;
1241
1242
  this.snapshotIdleHolds.delete(key);
1242
1243
  this.settledSnapshotIdleTasks.add(key);
1244
+ const task = this.tasks.get(hold.taskID);
1245
+ if (task?.parentSessionID === hold.parentSessionID && task.state === "running")
1246
+ this.tasks.delete(hold.taskID);
1247
+ }
1248
+ }
1249
+ markAbsentRunningChildren(parentSessionID, liveChildIDs) {
1250
+ for (const task of this.tasks.values()) {
1251
+ if (task.parentSessionID !== parentSessionID || task.state !== "running" || liveChildIDs.has(task.taskID))
1252
+ continue;
1253
+ this.markSnapshotIdle(parentSessionID, task.taskID);
1243
1254
  }
1244
1255
  }
1245
1256
  snapshotIdleKey(parentSessionID, taskID) {
@@ -1364,6 +1375,8 @@ var server = async ({ client }, options) => {
1364
1375
  await pauseGoalForPlanMode(sessionID);
1365
1376
  return;
1366
1377
  }
1378
+ if (busySessions.has(sessionID))
1379
+ return;
1367
1380
  if (!fromTaskDeferral && taskDeferredSessions.has(sessionID)) {
1368
1381
  scheduleSettledContinuation(sessionID);
1369
1382
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prevalentware/opencode-goal-plugin",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "description": "OpenCode goal plugin that adds Codex-style long-running goal mode, /goal commands, persistence, and TUI status for AI coding agents.",
5
5
  "keywords": [
6
6
  "opencode",
package/src/tui.tsx CHANGED
@@ -82,6 +82,27 @@ type ModernTuiApi = TuiPluginApi & {
82
82
 
83
83
  const goalCache = new Map<string, GoalSnapshot>()
84
84
 
85
+ function goalSnapshotKey(sessionID: string) {
86
+ return `goal-mode.snapshot.${sessionID}`
87
+ }
88
+
89
+ function cachedGoal(api: TuiPluginApi, sessionID: string) {
90
+ const memory = goalCache.get(sessionID)
91
+ if (memory) return memory
92
+ const persisted = api.kv?.get(goalSnapshotKey(sessionID), null)
93
+ return isGoalSnapshot(persisted) ? persisted : null
94
+ }
95
+
96
+ function cacheGoal(api: TuiPluginApi, sessionID: string, goal: GoalSnapshot | null) {
97
+ if (goal) {
98
+ goalCache.set(sessionID, goal)
99
+ api.kv?.set(goalSnapshotKey(sessionID), goal)
100
+ return
101
+ }
102
+ goalCache.delete(sessionID)
103
+ api.kv?.set(goalSnapshotKey(sessionID), null)
104
+ }
105
+
85
106
  function currentSessionID(api: TuiPluginApi) {
86
107
  const route = api.route.current
87
108
  if (route.name !== "session") return undefined
@@ -279,13 +300,12 @@ export function goalStateFromSession(api: TuiPluginApi, sessionID: string): Goal
279
300
  for (const part of parts) {
280
301
  const goal = parseGoalToolOutput(part)
281
302
  if (goal !== undefined) {
282
- if (goal) goalCache.set(sessionID, goal)
283
- else goalCache.delete(sessionID)
303
+ cacheGoal(api, sessionID, goal)
284
304
  return { goal, messageIndex }
285
305
  }
286
306
  }
287
307
  }
288
- return { goal: goalCache.get(sessionID) ?? null, messageIndex: -1 }
308
+ return { goal: cachedGoal(api, sessionID), messageIndex: -1 }
289
309
  }
290
310
 
291
311
  function goalFromSession(api: TuiPluginApi, sessionID: string) {