@prevalentware/opencode-goal-plugin 0.1.13 → 0.1.15

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/tui.tsx +12 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prevalentware/opencode-goal-plugin",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "Codex-style long-running goal mode for OpenCode.",
5
5
  "keywords": [
6
6
  "opencode",
package/src/tui.tsx CHANGED
@@ -37,6 +37,8 @@ type GoalSessionState = {
37
37
  messageIndex: number
38
38
  }
39
39
 
40
+ const goalCache = new Map<string, GoalSnapshot>()
41
+
40
42
  function currentSessionID(api: TuiPluginApi) {
41
43
  const route = api.route.current
42
44
  if (route.name !== "session") return undefined
@@ -111,7 +113,7 @@ function sessionIDOrToast(api: TuiPluginApi) {
111
113
  return sessionID
112
114
  }
113
115
 
114
- function formatDuration(seconds: number) {
116
+ export function formatDuration(seconds: number) {
115
117
  const total = Math.max(0, Math.floor(seconds))
116
118
  const hours = Math.floor(total / 3600)
117
119
  const minutes = Math.floor((total % 3600) / 60)
@@ -175,7 +177,7 @@ function parseGoalToolOutput(part: GoalToolPart): GoalSnapshot | null | undefine
175
177
  }
176
178
  }
177
179
 
178
- function goalStateFromSession(api: TuiPluginApi, sessionID: string): GoalSessionState {
180
+ export function goalStateFromSession(api: TuiPluginApi, sessionID: string): GoalSessionState {
179
181
  const messages = [...api.state.session.messages(sessionID)] as SessionMessage[]
180
182
  for (let messageIndex = messages.length - 1; messageIndex >= 0; messageIndex -= 1) {
181
183
  const message = messages[messageIndex]
@@ -183,10 +185,14 @@ function goalStateFromSession(api: TuiPluginApi, sessionID: string): GoalSession
183
185
  const parts = [...api.state.part(message.id)].reverse() as GoalToolPart[]
184
186
  for (const part of parts) {
185
187
  const goal = parseGoalToolOutput(part)
186
- if (goal !== undefined) return { goal, messageIndex }
188
+ if (goal !== undefined) {
189
+ if (goal) goalCache.set(sessionID, goal)
190
+ else goalCache.delete(sessionID)
191
+ return { goal, messageIndex }
192
+ }
187
193
  }
188
194
  }
189
- return { goal: null, messageIndex: -1 }
195
+ return { goal: goalCache.get(sessionID) ?? null, messageIndex: -1 }
190
196
  }
191
197
 
192
198
  function goalFromSession(api: TuiPluginApi, sessionID: string) {
@@ -202,7 +208,7 @@ function formatGoal(goal: GoalSnapshot | null) {
202
208
  const lines = [
203
209
  `Objective: ${goal.objective}`,
204
210
  `Status: ${visibleStatus(goal.status)}`,
205
- `Time used: ${goal.timeUsedSeconds}s`,
211
+ `Time used: ${formatDuration(goal.timeUsedSeconds)}`,
206
212
  ]
207
213
  if (goal.completionEvidence) lines.push(`Completion evidence: ${goal.completionEvidence}`)
208
214
  if (goal.blocker) lines.push(`Blocker: ${goal.blocker}`)
@@ -223,10 +229,7 @@ function GoalSidebar(props: { api: TuiPluginApi; sessionID: string }) {
223
229
  const value = goal()
224
230
  return value ? liveTimeUsedSeconds(value, nowSeconds()) : 0
225
231
  })
226
- const objective = createMemo(() => {
227
- const value = goal()?.objective ?? ""
228
- return value.length > 72 ? `${value.slice(0, 69)}...` : value
229
- })
232
+ const objective = createMemo(() => goal()?.objective ?? "")
230
233
 
231
234
  return (
232
235
  <Show when={goal()}>