@prevalentware/opencode-goal-plugin 0.1.48 → 0.1.50
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/README.md +23 -3
- package/dist/server.js +860 -158
- package/package.json +15 -6
- package/src/i18n.ts +532 -0
- package/src/tui.ts +211 -91
package/src/tui.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { TuiCommand, TuiPlugin, TuiPluginApi, TuiPluginModule } from "@opencode-ai/plugin/tui"
|
|
2
|
-
import type { Plugin as TuiPluginV2 } from "@opencode
|
|
3
|
-
import type { SessionMessageInfo } from "@opencode
|
|
2
|
+
import type { Plugin as TuiPluginV2 } from "@opencode/plugin/tui"
|
|
3
|
+
import type { SessionMessageInfo } from "@opencode/client"
|
|
4
4
|
import { createElement, insert, setProp } from "@opentui/solid"
|
|
5
5
|
import { createEffect, createMemo, createSignal, onCleanup } from "solid-js"
|
|
6
|
+
import type { GoalMessages } from "./i18n"
|
|
7
|
+
import { messagesFor, presentGoalLastStatus, presentGoalStatus, presentGoalStopReason, resolveLocale } from "./i18n"
|
|
6
8
|
|
|
7
9
|
type GoalCheckpoint = {
|
|
8
10
|
summary: string
|
|
@@ -194,8 +196,13 @@ function currentSessionID(api: TuiPluginApi) {
|
|
|
194
196
|
return typeof sessionID === "string" ? sessionID : undefined
|
|
195
197
|
}
|
|
196
198
|
|
|
197
|
-
function toast(
|
|
198
|
-
api
|
|
199
|
+
function toast(
|
|
200
|
+
api: TuiPluginApi,
|
|
201
|
+
messages: GoalMessages,
|
|
202
|
+
message: string,
|
|
203
|
+
variant: "info" | "success" | "warning" | "error" = "info",
|
|
204
|
+
) {
|
|
205
|
+
api.ui.toast({ title: messages.tui.title, message, variant, duration: 2500 })
|
|
199
206
|
}
|
|
200
207
|
|
|
201
208
|
async function sendGoalPrompt(api: TuiPluginApi, sessionID: string, text: string) {
|
|
@@ -205,27 +212,35 @@ async function sendGoalPrompt(api: TuiPluginApi, sessionID: string, text: string
|
|
|
205
212
|
})
|
|
206
213
|
}
|
|
207
214
|
|
|
208
|
-
function refreshGoalPrompt() {
|
|
209
|
-
return
|
|
215
|
+
function refreshGoalPrompt(messages: GoalMessages) {
|
|
216
|
+
return messages.tui.refreshPrompt
|
|
210
217
|
}
|
|
211
218
|
|
|
212
|
-
function clearGoalPrompt() {
|
|
213
|
-
return
|
|
219
|
+
function clearGoalPrompt(messages: GoalMessages) {
|
|
220
|
+
return messages.tui.clearPrompt
|
|
214
221
|
}
|
|
215
222
|
|
|
216
|
-
function pauseGoalPrompt() {
|
|
217
|
-
return
|
|
223
|
+
function pauseGoalPrompt(messages: GoalMessages) {
|
|
224
|
+
return messages.tui.pausePrompt
|
|
218
225
|
}
|
|
219
226
|
|
|
220
|
-
function resumeGoalPrompt() {
|
|
221
|
-
return
|
|
227
|
+
function resumeGoalPrompt(messages: GoalMessages) {
|
|
228
|
+
return messages.tui.resumePrompt
|
|
222
229
|
}
|
|
223
230
|
|
|
224
|
-
function historyGoalPrompt() {
|
|
225
|
-
return
|
|
231
|
+
function historyGoalPrompt(messages: GoalMessages) {
|
|
232
|
+
return messages.tui.historyPrompt
|
|
226
233
|
}
|
|
227
234
|
|
|
228
|
-
function actionOption(
|
|
235
|
+
function actionOption(
|
|
236
|
+
api: TuiPluginApi,
|
|
237
|
+
messages: GoalMessages,
|
|
238
|
+
sessionID: string,
|
|
239
|
+
title: string,
|
|
240
|
+
value: string,
|
|
241
|
+
description: string,
|
|
242
|
+
prompt: string,
|
|
243
|
+
) {
|
|
229
244
|
return {
|
|
230
245
|
title,
|
|
231
246
|
value,
|
|
@@ -233,25 +248,75 @@ function actionOption(api: TuiPluginApi, sessionID: string, title: string, value
|
|
|
233
248
|
onSelect: () => {
|
|
234
249
|
void sendGoalPrompt(api, sessionID, prompt)
|
|
235
250
|
.then(() => api.ui.dialog.clear())
|
|
236
|
-
.catch((error) => toast(api, error instanceof Error ? error.message : String(error), "error"))
|
|
251
|
+
.catch((error) => toast(api, messages, error instanceof Error ? error.message : String(error), "error"))
|
|
237
252
|
},
|
|
238
253
|
}
|
|
239
254
|
}
|
|
240
255
|
|
|
241
|
-
function showSummary(
|
|
256
|
+
function showSummary(
|
|
257
|
+
api: TuiPluginApi,
|
|
258
|
+
messages: GoalMessages,
|
|
259
|
+
locale: ReturnType<typeof resolveLocale>,
|
|
260
|
+
sessionID: string,
|
|
261
|
+
goal: GoalSnapshot | null,
|
|
262
|
+
) {
|
|
242
263
|
const DialogSelect = api.ui.DialogSelect
|
|
243
264
|
const options = [
|
|
244
|
-
actionOption(
|
|
265
|
+
actionOption(
|
|
266
|
+
api,
|
|
267
|
+
messages,
|
|
268
|
+
sessionID,
|
|
269
|
+
messages.tui.refresh,
|
|
270
|
+
"refresh",
|
|
271
|
+
messages.tui.refreshDescription,
|
|
272
|
+
refreshGoalPrompt(messages),
|
|
273
|
+
),
|
|
245
274
|
...(goal
|
|
246
275
|
? [
|
|
247
|
-
actionOption(
|
|
276
|
+
actionOption(
|
|
277
|
+
api,
|
|
278
|
+
messages,
|
|
279
|
+
sessionID,
|
|
280
|
+
messages.tui.history,
|
|
281
|
+
"history",
|
|
282
|
+
messages.tui.historyDescription,
|
|
283
|
+
historyGoalPrompt(messages),
|
|
284
|
+
),
|
|
248
285
|
...(goal.status === "active"
|
|
249
|
-
? [
|
|
286
|
+
? [
|
|
287
|
+
actionOption(
|
|
288
|
+
api,
|
|
289
|
+
messages,
|
|
290
|
+
sessionID,
|
|
291
|
+
messages.tui.pause,
|
|
292
|
+
"pause",
|
|
293
|
+
messages.tui.pauseDescription,
|
|
294
|
+
pauseGoalPrompt(messages),
|
|
295
|
+
),
|
|
296
|
+
]
|
|
250
297
|
: []),
|
|
251
298
|
...(goal.status === "paused" || goal.status === "budgetLimited" || goal.status === "usageLimited"
|
|
252
|
-
? [
|
|
299
|
+
? [
|
|
300
|
+
actionOption(
|
|
301
|
+
api,
|
|
302
|
+
messages,
|
|
303
|
+
sessionID,
|
|
304
|
+
messages.tui.resume,
|
|
305
|
+
"resume",
|
|
306
|
+
messages.tui.resumeDescription,
|
|
307
|
+
resumeGoalPrompt(messages),
|
|
308
|
+
),
|
|
309
|
+
]
|
|
253
310
|
: []),
|
|
254
|
-
actionOption(
|
|
311
|
+
actionOption(
|
|
312
|
+
api,
|
|
313
|
+
messages,
|
|
314
|
+
sessionID,
|
|
315
|
+
messages.tui.clear,
|
|
316
|
+
"clear",
|
|
317
|
+
messages.tui.clearDescription,
|
|
318
|
+
clearGoalPrompt(messages),
|
|
319
|
+
),
|
|
255
320
|
]
|
|
256
321
|
: []),
|
|
257
322
|
]
|
|
@@ -259,8 +324,8 @@ function showSummary(api: TuiPluginApi, sessionID: string, goal: GoalSnapshot |
|
|
|
259
324
|
api.ui.dialog.setSize("large")
|
|
260
325
|
api.ui.dialog.replace(() =>
|
|
261
326
|
DialogSelect({
|
|
262
|
-
title:
|
|
263
|
-
placeholder: formatGoal(goal),
|
|
327
|
+
title: messages.tui.title,
|
|
328
|
+
placeholder: formatGoal(goal, messages, locale),
|
|
264
329
|
options,
|
|
265
330
|
onSelect(option) {
|
|
266
331
|
option.onSelect?.()
|
|
@@ -269,9 +334,9 @@ function showSummary(api: TuiPluginApi, sessionID: string, goal: GoalSnapshot |
|
|
|
269
334
|
)
|
|
270
335
|
}
|
|
271
336
|
|
|
272
|
-
function sessionIDOrToast(api: TuiPluginApi) {
|
|
337
|
+
function sessionIDOrToast(api: TuiPluginApi, messages: GoalMessages) {
|
|
273
338
|
const sessionID = currentSessionID(api)
|
|
274
|
-
if (!sessionID) toast(api,
|
|
339
|
+
if (!sessionID) toast(api, messages, messages.tui.openSession, "warning")
|
|
275
340
|
return sessionID
|
|
276
341
|
}
|
|
277
342
|
|
|
@@ -384,34 +449,37 @@ function goalFromSession(api: TuiPluginApi, sessionID: string) {
|
|
|
384
449
|
return goalStateFromSession(api, sessionID).goal
|
|
385
450
|
}
|
|
386
451
|
|
|
387
|
-
function formatGoal(goal: GoalSnapshot | null) {
|
|
388
|
-
if (!goal) return
|
|
452
|
+
export function formatGoal(goal: GoalSnapshot | null, messages: GoalMessages, locale: ReturnType<typeof resolveLocale>) {
|
|
453
|
+
if (!goal) return messages.tui.noGoal
|
|
389
454
|
const lines = [
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
455
|
+
`${messages.tui.objective}: ${goal.objective}`,
|
|
456
|
+
`${messages.tui.status}: ${presentGoalStatus(goal.status, locale)}`,
|
|
457
|
+
`${messages.tui.timeUsed}: ${formatDuration(goal.timeUsedSeconds)}`,
|
|
458
|
+
`${messages.tui.tokens}: ${goal.tokensUsed}${goal.tokenBudget == null ? "" : `/${goal.tokenBudget}`}`,
|
|
459
|
+
`${messages.tui.autoContinues}: ${goal.autoTurns}${goal.maxAutoTurns == null ? "" : `/${goal.maxAutoTurns}`}`,
|
|
395
460
|
]
|
|
396
|
-
if (goal.remainingTokens != null) lines.push(
|
|
397
|
-
if (goal.maxDurationSeconds != null) lines.push(
|
|
398
|
-
if (goal.noProgressTurns > 0) lines.push(
|
|
399
|
-
if (goal.lastCheckpoint) lines.push(
|
|
400
|
-
if (goal.stopReason) lines.push(
|
|
401
|
-
if (goal.lastStatus) lines.push(
|
|
402
|
-
if (goal.completionEvidence) lines.push(
|
|
403
|
-
if (goal.blocker) lines.push(
|
|
461
|
+
if (goal.remainingTokens != null) lines.push(`${messages.tui.tokensRemaining}: ${goal.remainingTokens}`)
|
|
462
|
+
if (goal.maxDurationSeconds != null) lines.push(`${messages.tui.durationLimit}: ${formatDuration(goal.maxDurationSeconds)}`)
|
|
463
|
+
if (goal.noProgressTurns > 0) lines.push(`${messages.tui.noProgressTurns}: ${goal.noProgressTurns}`)
|
|
464
|
+
if (goal.lastCheckpoint) lines.push(`${messages.tui.latestCheckpoint}: ${goal.lastCheckpoint.summary}`)
|
|
465
|
+
if (goal.stopReason) lines.push(`${messages.tui.stopReason}: ${presentGoalStopReason(goal.stopReason, locale)}`)
|
|
466
|
+
if (goal.lastStatus) lines.push(`${messages.tui.lastStatus}: ${presentGoalLastStatus(goal.lastStatus, locale)}`)
|
|
467
|
+
if (goal.completionEvidence) lines.push(`${messages.tui.completionEvidence}: ${goal.completionEvidence}`)
|
|
468
|
+
if (goal.blocker) lines.push(`${messages.tui.blocker}: ${presentGoalLastStatus(goal.blocker, locale)}`)
|
|
404
469
|
return lines.join("\n")
|
|
405
470
|
}
|
|
406
471
|
|
|
407
|
-
function GoalSidebar(api: TuiPluginApi, sessionID: string) {
|
|
472
|
+
function GoalSidebar(api: TuiPluginApi, messages: GoalMessages, locale: ReturnType<typeof resolveLocale>, sessionID: string) {
|
|
408
473
|
const theme = api.theme.current
|
|
409
474
|
const state = goalStateFromSession(api, sessionID)
|
|
410
475
|
const goal = state.goal
|
|
411
476
|
if (!goal) return null
|
|
412
477
|
if (goal.status === "complete" || goal.status === "unmet") {
|
|
413
478
|
const elapsed = liveTimeUsedSeconds(goal)
|
|
414
|
-
|
|
479
|
+
const label = goal.status === "complete" ? messages.tui.achieved : messages.tui.unmet
|
|
480
|
+
return text({ fg: goal.status === "complete" ? theme.primary : theme.textMuted }, [
|
|
481
|
+
`${label} (${formatDurationBadge(elapsed)})`,
|
|
482
|
+
])
|
|
415
483
|
}
|
|
416
484
|
const [nowSeconds, setNowSeconds] = createSignal(currentEpochSeconds())
|
|
417
485
|
if (goal.status === "active") {
|
|
@@ -419,14 +487,22 @@ function GoalSidebar(api: TuiPluginApi, sessionID: string) {
|
|
|
419
487
|
onCleanup(() => clearInterval(timer))
|
|
420
488
|
}
|
|
421
489
|
return box({}, [
|
|
422
|
-
text({ fg: theme.text }, [
|
|
423
|
-
text({ fg: theme.textMuted }, [
|
|
424
|
-
text({ fg: theme.textMuted }, [() =>
|
|
425
|
-
text({ fg: theme.textMuted }, [
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
490
|
+
text({ fg: theme.text }, [messages.tui.title]),
|
|
491
|
+
text({ fg: theme.textMuted }, [`${messages.tui.status}: ${presentGoalStatus(goal.status, locale)}`]),
|
|
492
|
+
text({ fg: theme.textMuted }, [() => `${messages.tui.time}: ${formatDuration(liveTimeUsedSeconds(goal, nowSeconds()))}`]),
|
|
493
|
+
text({ fg: theme.textMuted }, [
|
|
494
|
+
`${messages.tui.tokens}: ${goal.tokensUsed}${goal.tokenBudget == null ? "" : `/${goal.tokenBudget}`}`,
|
|
495
|
+
]),
|
|
496
|
+
text({ fg: theme.textMuted }, [
|
|
497
|
+
`${messages.tui.autoContinues}: ${goal.autoTurns}${goal.maxAutoTurns == null ? "" : `/${goal.maxAutoTurns}`}`,
|
|
498
|
+
]),
|
|
499
|
+
...(goal.lastCheckpoint
|
|
500
|
+
? [text({ fg: theme.textMuted }, [`${messages.tui.checkpoint}: ${goal.lastCheckpoint.summary}`])]
|
|
501
|
+
: []),
|
|
502
|
+
...(goal.stopReason
|
|
503
|
+
? [text({ fg: theme.textMuted }, [`${messages.tui.stop}: ${presentGoalStopReason(goal.stopReason, locale)}`])]
|
|
504
|
+
: []),
|
|
505
|
+
...(goal.lastStatus ? [text({ fg: theme.textMuted }, [presentGoalLastStatus(goal.lastStatus, locale)])] : []),
|
|
430
506
|
text({ fg: theme.textMuted }, [goal.objective]),
|
|
431
507
|
])
|
|
432
508
|
}
|
|
@@ -452,25 +528,27 @@ function registerGoalCommand(api: TuiPluginApi, command: TuiCommand) {
|
|
|
452
528
|
api.command?.register(() => [command])
|
|
453
529
|
}
|
|
454
530
|
|
|
455
|
-
const tui: TuiPlugin = async (api) => {
|
|
531
|
+
const tui: TuiPlugin = async (api, options) => {
|
|
532
|
+
const locale = resolveLocale(typeof options?.locale === "string" ? options.locale : undefined)
|
|
533
|
+
const messages = messagesFor(locale)
|
|
456
534
|
api.slots.register({
|
|
457
535
|
order: 125,
|
|
458
536
|
slots: {
|
|
459
537
|
sidebar_content(_ctx, props) {
|
|
460
|
-
return GoalSidebar(api, props.session_id)
|
|
538
|
+
return GoalSidebar(api, messages, locale, props.session_id)
|
|
461
539
|
},
|
|
462
540
|
},
|
|
463
541
|
})
|
|
464
542
|
|
|
465
543
|
registerGoalCommand(api, {
|
|
466
|
-
title:
|
|
544
|
+
title: messages.tui.title,
|
|
467
545
|
value: "goal.show",
|
|
468
|
-
category:
|
|
469
|
-
description:
|
|
546
|
+
category: messages.tui.title,
|
|
547
|
+
description: messages.tui.commandDescription,
|
|
470
548
|
onSelect: () => {
|
|
471
|
-
const sessionID = sessionIDOrToast(api)
|
|
549
|
+
const sessionID = sessionIDOrToast(api, messages)
|
|
472
550
|
if (!sessionID) return
|
|
473
|
-
showSummary(api, sessionID, goalFromSession(api, sessionID))
|
|
551
|
+
showSummary(api, messages, locale, sessionID, goalFromSession(api, sessionID))
|
|
474
552
|
},
|
|
475
553
|
})
|
|
476
554
|
}
|
|
@@ -516,43 +594,63 @@ function currentSessionIDV2(api: TuiPluginV2.Context) {
|
|
|
516
594
|
return route.sessionID
|
|
517
595
|
}
|
|
518
596
|
|
|
519
|
-
function toastV2(
|
|
520
|
-
api
|
|
597
|
+
function toastV2(
|
|
598
|
+
api: TuiPluginV2.Context,
|
|
599
|
+
messages: GoalMessages,
|
|
600
|
+
message: string,
|
|
601
|
+
variant: "info" | "success" | "warning" | "error" = "info",
|
|
602
|
+
) {
|
|
603
|
+
api.ui.toast.show({ title: messages.tui.title, message, variant, duration: 2500 })
|
|
521
604
|
}
|
|
522
605
|
|
|
523
|
-
async function showSummaryV2(
|
|
606
|
+
async function showSummaryV2(
|
|
607
|
+
api: TuiPluginV2.Context,
|
|
608
|
+
messages: GoalMessages,
|
|
609
|
+
locale: ReturnType<typeof resolveLocale>,
|
|
610
|
+
sessionID: string,
|
|
611
|
+
goal: GoalSnapshot | null,
|
|
612
|
+
) {
|
|
524
613
|
const options = [
|
|
525
|
-
{ title:
|
|
614
|
+
{ title: messages.tui.refresh, value: "refresh", description: messages.tui.refreshDescription },
|
|
526
615
|
...(goal
|
|
527
616
|
? [
|
|
528
|
-
{ title:
|
|
617
|
+
{ title: messages.tui.history, value: "history", description: messages.tui.historyDescription },
|
|
529
618
|
...(goal.status === "active"
|
|
530
|
-
? [{ title:
|
|
619
|
+
? [{ title: messages.tui.pause, value: "pause", description: messages.tui.pauseDescription }]
|
|
531
620
|
: []),
|
|
532
621
|
...(goal.status === "paused" || goal.status === "budgetLimited" || goal.status === "usageLimited"
|
|
533
|
-
? [{ title:
|
|
622
|
+
? [{ title: messages.tui.resume, value: "resume", description: messages.tui.resumeDescription }]
|
|
534
623
|
: []),
|
|
535
|
-
{ title:
|
|
624
|
+
{ title: messages.tui.clear, value: "clear", description: messages.tui.clearDescription },
|
|
536
625
|
]
|
|
537
626
|
: []),
|
|
538
627
|
]
|
|
539
628
|
api.ui.dialog.set({ size: "large" })
|
|
540
|
-
const selected = await api.ui.dialog.select({
|
|
541
|
-
|
|
542
|
-
:
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
629
|
+
const selected = await api.ui.dialog.select({
|
|
630
|
+
title: messages.tui.title,
|
|
631
|
+
placeholder: formatGoal(goal, messages, locale),
|
|
632
|
+
options,
|
|
633
|
+
})
|
|
634
|
+
const prompt = selected === "refresh" ? refreshGoalPrompt(messages)
|
|
635
|
+
: selected === "history" ? historyGoalPrompt(messages)
|
|
636
|
+
: selected === "pause" ? pauseGoalPrompt(messages)
|
|
637
|
+
: selected === "resume" ? resumeGoalPrompt(messages)
|
|
638
|
+
: selected === "clear" ? clearGoalPrompt(messages)
|
|
546
639
|
: undefined
|
|
547
640
|
if (!prompt) return
|
|
548
641
|
try {
|
|
549
642
|
await api.client.session.prompt({ sessionID, text: prompt })
|
|
550
643
|
} catch (error) {
|
|
551
|
-
toastV2(api, error instanceof Error ? error.message : String(error), "error")
|
|
644
|
+
toastV2(api, messages, error instanceof Error ? error.message : String(error), "error")
|
|
552
645
|
}
|
|
553
646
|
}
|
|
554
647
|
|
|
555
|
-
function GoalSidebarV2(
|
|
648
|
+
function GoalSidebarV2(
|
|
649
|
+
api: TuiPluginV2.Context,
|
|
650
|
+
messages: GoalMessages,
|
|
651
|
+
locale: ReturnType<typeof resolveLocale>,
|
|
652
|
+
sessionID: string,
|
|
653
|
+
) {
|
|
556
654
|
const colors = goalColorsV2(api.theme)
|
|
557
655
|
const [cache, setCache] = api.storage.memory<{ goal: GoalSnapshot | null }>(`goal-mode.v2.${sessionID}`, {
|
|
558
656
|
initial: { goal: null },
|
|
@@ -579,40 +677,58 @@ function GoalSidebarV2(api: TuiPluginV2.Context, sessionID: string) {
|
|
|
579
677
|
if (snapshot.status === "complete" || snapshot.status === "unmet") {
|
|
580
678
|
const elapsed = liveTimeUsedSeconds(snapshot)
|
|
581
679
|
return text({ fg: snapshot.status === "complete" ? colors.achieved : colors.muted }, [
|
|
582
|
-
`${snapshot.status === "complete" ?
|
|
680
|
+
`${snapshot.status === "complete" ? messages.tui.achieved : messages.tui.unmet} (${formatDurationBadge(elapsed)})`,
|
|
583
681
|
])
|
|
584
682
|
}
|
|
585
683
|
return box({}, [
|
|
586
|
-
text({ fg: colors.text }, [
|
|
587
|
-
text({ fg: colors.muted }, [
|
|
588
|
-
text({ fg: colors.muted }, [
|
|
589
|
-
text({ fg: colors.muted }, [
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
684
|
+
text({ fg: colors.text }, [messages.tui.title]),
|
|
685
|
+
text({ fg: colors.muted }, [`${messages.tui.status}: ${presentGoalStatus(snapshot.status, locale)}`]),
|
|
686
|
+
text({ fg: colors.muted }, [`${messages.tui.time}: ${formatDuration(liveTimeUsedSeconds(snapshot, nowSeconds()))}`]),
|
|
687
|
+
text({ fg: colors.muted }, [
|
|
688
|
+
`${messages.tui.tokens}: ${snapshot.tokensUsed}${snapshot.tokenBudget == null ? "" : `/${snapshot.tokenBudget}`}`,
|
|
689
|
+
]),
|
|
690
|
+
text({ fg: colors.muted }, [
|
|
691
|
+
`${messages.tui.autoContinues}: ${snapshot.autoTurns}${
|
|
692
|
+
snapshot.maxAutoTurns == null ? "" : `/${snapshot.maxAutoTurns}`
|
|
693
|
+
}`,
|
|
694
|
+
]),
|
|
695
|
+
...(snapshot.lastCheckpoint
|
|
696
|
+
? [text({ fg: colors.muted }, [`${messages.tui.checkpoint}: ${snapshot.lastCheckpoint.summary}`])]
|
|
697
|
+
: []),
|
|
698
|
+
...(snapshot.stopReason
|
|
699
|
+
? [
|
|
700
|
+
text(
|
|
701
|
+
{ fg: colors.muted },
|
|
702
|
+
[`${messages.tui.stop}: ${presentGoalStopReason(snapshot.stopReason, locale)}`],
|
|
703
|
+
),
|
|
704
|
+
]
|
|
705
|
+
: []),
|
|
706
|
+
...(snapshot.lastStatus
|
|
707
|
+
? [text({ fg: colors.muted }, [presentGoalLastStatus(snapshot.lastStatus, locale)])]
|
|
708
|
+
: []),
|
|
594
709
|
text({ fg: colors.muted }, [snapshot.objective]),
|
|
595
710
|
])
|
|
596
711
|
}])
|
|
597
712
|
}
|
|
598
713
|
|
|
599
|
-
function GoalKeymapLayerV2(api: TuiPluginV2.Context) {
|
|
714
|
+
function GoalKeymapLayerV2(api: TuiPluginV2.Context, messages: GoalMessages, locale: ReturnType<typeof resolveLocale>) {
|
|
600
715
|
api.keymap.layer(() => ({
|
|
601
716
|
mode: "global",
|
|
602
717
|
commands: [
|
|
603
718
|
{
|
|
604
719
|
id: "goal.show",
|
|
605
|
-
title:
|
|
606
|
-
description:
|
|
607
|
-
group:
|
|
720
|
+
title: messages.tui.title,
|
|
721
|
+
description: messages.tui.commandDescription,
|
|
722
|
+
group: messages.tui.title,
|
|
608
723
|
palette: true,
|
|
609
724
|
run: () => {
|
|
610
725
|
const sessionID = currentSessionIDV2(api)
|
|
611
726
|
if (!sessionID) {
|
|
612
|
-
toastV2(api,
|
|
727
|
+
toastV2(api, messages, messages.tui.openSession, "warning")
|
|
613
728
|
return
|
|
614
729
|
}
|
|
615
|
-
|
|
730
|
+
const goal = goalFromV2Messages(api.data.session.message.list(sessionID)) ?? null
|
|
731
|
+
void showSummaryV2(api, messages, locale, sessionID, goal)
|
|
616
732
|
},
|
|
617
733
|
},
|
|
618
734
|
],
|
|
@@ -629,8 +745,12 @@ function GoalKeymapLayerV2(api: TuiPluginV2.Context) {
|
|
|
629
745
|
* needs to dispose the two `ui.slot` registrations.
|
|
630
746
|
*/
|
|
631
747
|
export function setupTuiV2(context: TuiPluginV2.Context): TuiPluginV2.Cleanup {
|
|
632
|
-
const
|
|
633
|
-
const
|
|
748
|
+
const locale = resolveLocale(typeof context.options?.locale === "string" ? context.options.locale : undefined)
|
|
749
|
+
const messages = messagesFor(locale)
|
|
750
|
+
const offSidebar = registerSlotV2(context, "sidebar.content", (props) =>
|
|
751
|
+
GoalSidebarV2(context, messages, locale, props.sessionID),
|
|
752
|
+
)
|
|
753
|
+
const offApp = registerSlotV2(context, "app", () => GoalKeymapLayerV2(context, messages, locale))
|
|
634
754
|
return () => {
|
|
635
755
|
offSidebar()
|
|
636
756
|
offApp()
|