opencode-extended-sidebar 0.2.90 → 0.2.91

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 (108) hide show
  1. package/.oesignore +17 -17
  2. package/CHANGELOG.md +96 -95
  3. package/LICENSE +21 -21
  4. package/README.md +150 -235
  5. package/oes.json +13 -11
  6. package/package.json +100 -100
  7. package/scripts/install-git-hooks.mjs +29 -29
  8. package/src/pware.oc.core/constants/index.ts +18 -18
  9. package/src/pware.oc.core/constants/pware.oc.core.constants.eventKind.ts +29 -29
  10. package/src/pware.oc.core/constants/pware.oc.core.constants.eventName.ts +15 -13
  11. package/src/pware.oc.core/constants/pware.oc.core.constants.eventType.ts +241 -241
  12. package/src/pware.oc.core/constants/pware.oc.core.constants.myWork.ts +55 -55
  13. package/src/pware.oc.core/constants/pware.oc.core.constants.partType.ts +65 -65
  14. package/src/pware.oc.core/constants/pware.oc.core.constants.phase.ts +58 -58
  15. package/src/pware.oc.core/constants/pware.oc.core.constants.pulse.ts +63 -63
  16. package/src/pware.oc.core/constants/pware.oc.core.constants.rowKind.ts +34 -34
  17. package/src/pware.oc.core/constants/pware.oc.core.constants.status.ts +74 -74
  18. package/src/pware.oc.core/constants/pware.oc.core.constants.toolName.ts +69 -69
  19. package/src/pware.oc.core/git/index.ts +7 -7
  20. package/src/pware.oc.core/git/pware.oc.core.git.ts +237 -237
  21. package/src/pware.oc.core/git/pware.oc.core.gitignore.ts +87 -87
  22. package/src/pware.oc.core/index.ts +19 -18
  23. package/src/pware.oc.core/pware.oc.core.bus.ts +42 -42
  24. package/src/pware.oc.core/pware.oc.core.cache.ts +48 -48
  25. package/src/pware.oc.core/pware.oc.core.clipboard.ts +97 -97
  26. package/src/pware.oc.core/pware.oc.core.debug.ts +280 -280
  27. package/src/pware.oc.core/pware.oc.core.events.ts +79 -79
  28. package/src/pware.oc.core/pware.oc.core.glyph.ts +135 -135
  29. package/src/pware.oc.core/pware.oc.core.layout.ts +234 -234
  30. package/src/pware.oc.core/pware.oc.core.oes.ts +99 -89
  31. package/src/pware.oc.core/pware.oc.core.paths.ts +240 -240
  32. package/src/pware.oc.core/pware.oc.core.preview.ts +74 -74
  33. package/src/pware.oc.core/pware.oc.core.pulse.ts +726 -726
  34. package/src/pware.oc.core/pware.oc.core.runtimeConfig.ts +41 -0
  35. package/src/pware.oc.core/pware.oc.core.sqlite.ts +164 -175
  36. package/src/pware.oc.core/pware.oc.core.sqliteGateway.ts +89 -0
  37. package/src/pware.oc.core/pware.oc.core.status.ts +214 -214
  38. package/src/pware.oc.core/pware.oc.core.timing.ts +63 -63
  39. package/src/pware.oc.core/pware.oc.core.width.ts +215 -215
  40. package/src/pware.oc.omo/constants/index.ts +15 -15
  41. package/src/pware.oc.omo/constants/pware.oc.omo.constants.backgroundTask.ts +18 -18
  42. package/src/pware.oc.omo/constants/pware.oc.omo.constants.boulderStatus.ts +49 -49
  43. package/src/pware.oc.omo/constants/pware.oc.omo.constants.docKind.ts +29 -29
  44. package/src/pware.oc.omo/constants/pware.oc.omo.constants.eventName.ts +11 -11
  45. package/src/pware.oc.omo/constants/pware.oc.omo.constants.planStatus.ts +60 -60
  46. package/src/pware.oc.omo/constants/pware.oc.omo.constants.reviewStatus.ts +49 -49
  47. package/src/pware.oc.omo/constants/pware.oc.omo.constants.startWork.ts +25 -25
  48. package/src/pware.oc.omo/constants/pware.oc.omo.constants.verdict.ts +38 -38
  49. package/src/pware.oc.omo/index.ts +7 -7
  50. package/src/pware.oc.omo/resolver/index.ts +19 -19
  51. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.approval.ts +179 -179
  52. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.approvalGroup.ts +116 -116
  53. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.approvalState.ts +34 -34
  54. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.boulder.ts +503 -503
  55. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.config.ts +40 -40
  56. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.doc.ts +269 -269
  57. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.draftFile.ts +18 -18
  58. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.notepadsFile.ts +18 -18
  59. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.plan.ts +155 -155
  60. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.planFile.ts +363 -361
  61. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.proofFile.ts +18 -18
  62. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.rulesFile.ts +11 -11
  63. package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.runContinuationFile.ts +14 -14
  64. package/src/pware.oc.opencode/constants/index.ts +10 -10
  65. package/src/pware.oc.opencode/constants/pware.oc.opencode.constants.eventName.ts +15 -15
  66. package/src/pware.oc.opencode/constants/pware.oc.opencode.constants.fileTouch.ts +18 -18
  67. package/src/pware.oc.opencode/constants/pware.oc.opencode.constants.questionKind.ts +45 -45
  68. package/src/pware.oc.opencode/constants/pware.oc.opencode.constants.sessionStatus.ts +58 -58
  69. package/src/pware.oc.opencode/index.ts +8 -8
  70. package/src/pware.oc.opencode/pware.oc.opencode.events.ts +182 -182
  71. package/src/pware.oc.opencode/pware.oc.opencode.files.ts +399 -399
  72. package/src/pware.oc.opencode/resolver/index.ts +223 -170
  73. package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.file.ts +150 -162
  74. package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.question.ts +149 -185
  75. package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.session.ts +248 -211
  76. package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.todo.ts +22 -26
  77. package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.tool.ts +224 -236
  78. package/src/pware.oc.perf/index.ts +14 -14
  79. package/src/pware.oc.perf/pware.oc.perf.asciichart.d.ts +15 -15
  80. package/src/pware.oc.perf/pware.oc.perf.charts.ts +284 -284
  81. package/src/pware.oc.perf/pware.oc.perf.reader.ts +962 -927
  82. package/src/pware.oc.perf/pware.oc.perf.realtime.ts +88 -88
  83. package/src/pware.oc.perf/pware.oc.perf.realtimeBlock.ts +118 -118
  84. package/src/pware.oc.perf/pware.oc.perf.realtimeCpuRam.ts +79 -79
  85. package/src/pware.oc.perf/pware.oc.perf.realtimeSampler.ts +71 -71
  86. package/src/pware.oc.perf/pware.oc.perf.realtimeTimeline.ts +214 -214
  87. package/src/pware.oc.perf/pware.oc.perf.self.ts +179 -179
  88. package/src/pware.oc.perf/pware.oc.perf.view.tsx +463 -462
  89. package/src/pware.oc.runtime/index.ts +13 -13
  90. package/src/pware.oc.runtime/pware.oc.runtime.monitor.ts +142 -142
  91. package/src/pware.oc.runtime/pware.oc.runtime.mywork-enrich.ts +87 -79
  92. package/src/pware.oc.runtime/pware.oc.runtime.mywork.ts +282 -253
  93. package/src/pware.oc.runtime/pware.oc.runtime.omoRead.ts +37 -0
  94. package/src/pware.oc.runtime/pware.oc.runtime.questions.ts +83 -95
  95. package/src/pware.oc.runtime/pware.oc.runtime.snapshotClient.ts +130 -129
  96. package/src/pware.oc.runtime/pware.oc.runtime.source.ts +105 -105
  97. package/src/pware.oc.runtime/pware.oc.runtime.worker.ts +44 -43
  98. package/src/pware.oc.runtime/resolver/index.ts +268 -224
  99. package/src/pware.oc.runtime/resolver/pware.oc.runtime.resolver.delegate.ts +146 -146
  100. package/src/pware.oc.ui/index.ts +12 -12
  101. package/src/pware.oc.ui/pware.oc.ui.chrome.tsx +381 -339
  102. package/src/pware.oc.ui/pware.oc.ui.glyphs.tsx +144 -144
  103. package/src/pware.oc.ui/pware.oc.ui.host.tsx +111 -111
  104. package/src/pware.oc.ui/pware.oc.ui.live.tsx +82 -82
  105. package/src/pware.oc.ui/pware.oc.ui.menudialogs.tsx +843 -843
  106. package/src/pware.oc.ui/pware.oc.ui.sections.tsx +552 -526
  107. package/src/pware.oc.ui/pware.oc.ui.sidebar.tsx +1718 -1629
  108. package/src/pware.oc.ui.tsx +98 -98
@@ -1,144 +1,144 @@
1
- /**
2
- * pware.oc.ui.glyphs
3
- *
4
- * Domain glyph definitions (My work kinds, git letters, review lanes) that
5
- * depend on opencode / omo / runtime types, so they cannot live in core. Each
6
- * returns a complete `GlyphSpec` (char + tone). The pure mark/flow glyphs live
7
- * in core (`pware.oc.core/pware.oc.core.glyph.ts`) and are re-exported here so
8
- * every glyph resolves through this one module.
9
- */
10
- import type { FileLetter } from "../pware.oc.opencode/pware.oc.opencode.files.js"
11
- import type { MyWorkKind } from "../pware.oc.runtime/pware.oc.runtime.mywork.js"
12
- import type { ReviewLane, ReviewState } from "../pware.oc.omo/resolver/pware.oc.omo.resolver.plan.js"
13
- import {
14
- REVIEW_STATUS_APPROVED,
15
- REVIEW_STATUS_CHANGES_REQUESTED,
16
- REVIEW_STATUS_INCONCLUSIVE,
17
- REVIEW_STATUS_PENDING,
18
- ROUND_STATUS_ACTIVE,
19
- } from "../pware.oc.omo/constants/pware.oc.omo.constants.reviewStatus.js"
20
- import {
21
- MY_WORK_GROUP_DISMISSED,
22
- MY_WORK_GROUP_DRAFT_DOCS,
23
- MY_WORK_GROUP_DRAFTING,
24
- MY_WORK_GROUP_FINISHED,
25
- MY_WORK_GROUP_PINNED,
26
- MY_WORK_GROUP_PLANS,
27
- MY_WORK_GROUP_READY_REVIEW,
28
- MY_WORK_GROUP_READY_START,
29
- MY_WORK_GROUP_SESSIONS,
30
- } from "../pware.oc.core/constants/pware.oc.core.constants.myWork.js"
31
- import {
32
- QUESTION_KIND_ERROR,
33
- QUESTION_KIND_INTERRUPTED,
34
- QUESTION_KIND_QUESTION,
35
- } from "../pware.oc.opencode/constants/pware.oc.opencode.constants.questionKind.js"
36
- import type { GlyphSpec } from "../pware.oc.core/pware.oc.core.glyph.js"
37
-
38
- export { workStatusGlyph } from "../pware.oc.core/pware.oc.core.status.js"
39
- export {
40
- SPINNER_FRAMES,
41
- QUEUED_GLYPH,
42
- ENGAGE_MIN_FRAMES,
43
- ENGAGE_MAX_FRAMES,
44
- spinnerFrame,
45
- engageFill,
46
- engageDone,
47
- flowBlinkOn,
48
- sinPulseAlpha,
49
- type SinPulseAlphaOpts,
50
- markTone,
51
- stateGlyph,
52
- directionGlyph,
53
- defaultBodyTone,
54
- type GlyphSpec,
55
- type ToneKey,
56
- } from "../pware.oc.core/pware.oc.core.glyph.js"
57
-
58
- /** Group header before a clustered row list. */
59
- export const GROUP_GLYPH = "▾"
60
- /** Perf: a phase of the wall clock spent thinking. */
61
- export const THINK_GLYPH = "∴"
62
-
63
- /** The glyph for a My work kind — a complete spec; the tone says how urgent it is. */
64
- export function myWorkGlyph(kind: MyWorkKind): GlyphSpec {
65
- if (kind === QUESTION_KIND_QUESTION) return { char: "?", tone: "warning" }
66
- if (kind === QUESTION_KIND_INTERRUPTED) return { char: "⊘", tone: "textMuted" }
67
- if (kind === QUESTION_KIND_ERROR) return { char: "×", tone: "error" }
68
- if (kind === MY_WORK_GROUP_SESSIONS) return { char: "◔", tone: "primary" }
69
- if (kind === MY_WORK_GROUP_PINNED) return { char: "P", tone: "primary" }
70
- if (kind === MY_WORK_GROUP_READY_REVIEW) return { char: "!", tone: "warning" }
71
- if (kind === MY_WORK_GROUP_DRAFTING) return { char: "…", tone: "textMuted" }
72
- if (kind === MY_WORK_GROUP_DRAFT_DOCS) return { char: "•", tone: "textMuted" }
73
- if (kind === MY_WORK_GROUP_PLANS) return { char: "▸", tone: "textMuted" }
74
- if (kind === MY_WORK_GROUP_READY_START) return { char: "▶", tone: "primary" }
75
- if (kind === MY_WORK_GROUP_FINISHED) return { char: "✓", tone: "success" }
76
- if (kind === MY_WORK_GROUP_DISMISSED) return { char: "⊘", tone: "textMuted" }
77
- return { char: "!", tone: "warning" }
78
- }
79
-
80
- /**
81
- * Neutral tab-header light: a small muted bullet, shown when nothing is
82
- * waiting on the user (and for every non-My-work tab).
83
- */
84
- export const TAB_NEUTRAL_GLYPH: GlyphSpec = { char: "•", tone: "textMuted" }
85
-
86
- /** One item the My-work tab light reasons about. `ended` marks a terminated part. */
87
- export type TabAttentionItem = {
88
- kind: MyWorkKind
89
- /** True when the part already has a terminal end time — history, not live. */
90
- ended?: boolean
91
- }
92
-
93
- /**
94
- * The tab light's winner list, most urgent first. A live open question beats
95
- * everything; an *ended* error is history (the panel still lists it in Errors)
96
- * and never lights the tab; running/drafting/finished are not waiting on you.
97
- */
98
- const TAB_ATTENTION_PRIORITY: readonly ((i: TabAttentionItem) => boolean)[] = [
99
- (i) => i.kind === QUESTION_KIND_QUESTION,
100
- (i) => i.kind === QUESTION_KIND_ERROR && !i.ended,
101
- (i) => i.kind === MY_WORK_GROUP_READY_REVIEW,
102
- (i) => i.kind === MY_WORK_GROUP_READY_START,
103
- (i) => i.kind === QUESTION_KIND_INTERRUPTED && !i.ended,
104
- ]
105
-
106
- /** The My-work tab light: the most urgent live waiting item, or a neutral bullet. */
107
- export function tabAttentionGlyph(items: readonly TabAttentionItem[]): GlyphSpec {
108
- for (const match of TAB_ATTENTION_PRIORITY) {
109
- for (const item of items) {
110
- if (match(item)) return myWorkGlyph(item.kind)
111
- }
112
- }
113
- return TAB_NEUTRAL_GLYPH
114
- }
115
-
116
- /** A git-status letter as a glyph: added green, deleted red, modified yellow, rest muted. */
117
- export function fileLetterGlyph(letter: FileLetter | null): GlyphSpec {
118
- const char = letter ?? "•"
119
- const tone =
120
- letter === "A" ? "success" : letter === "D" ? "error" : letter === "M" ? "warning" : "textMuted"
121
- return { char, tone }
122
- }
123
-
124
- /** One ulw-plan review lane: ✓ approved, ! changes, ? inconclusive, … live, · pending. */
125
- export function reviewLaneGlyph(lane: ReviewLane | null | undefined): GlyphSpec {
126
- const s = lane?.status
127
- if (s === REVIEW_STATUS_APPROVED) return { char: "✓", tone: "success" }
128
- if (s === REVIEW_STATUS_CHANGES_REQUESTED) return { char: "!", tone: "warning" }
129
- if (s === REVIEW_STATUS_INCONCLUSIVE) return { char: "?", tone: "warning" }
130
- if (s === REVIEW_STATUS_PENDING || !s) return { char: "·", tone: "textMuted" }
131
- return { char: "…", tone: "textMuted" }
132
- }
133
-
134
- /**
135
- * Compact review state for a plan row: `R<round> <momus><independent>` while a
136
- * round is recorded, otherwise just the two lanes. Null when no review exists.
137
- */
138
- export function reviewStateSuffix(review: ReviewState | null | undefined): string | null {
139
- if (!review || (!review.required && !review.roundId && !review.roundStatus)) return null
140
- const lanes = `${reviewLaneGlyph(review.lanes.momus).char}${reviewLaneGlyph(review.lanes.independent).char}`
141
- if (review.roundId) return `R${review.roundId} ${lanes}`
142
- if (review.roundStatus === ROUND_STATUS_ACTIVE) return `R… ${lanes}`
143
- return lanes
144
- }
1
+ /**
2
+ * pware.oc.ui.glyphs
3
+ *
4
+ * Domain glyph definitions (My work kinds, git letters, review lanes) that
5
+ * depend on opencode / omo / runtime types, so they cannot live in core. Each
6
+ * returns a complete `GlyphSpec` (char + tone). The pure mark/flow glyphs live
7
+ * in core (`pware.oc.core/pware.oc.core.glyph.ts`) and are re-exported here so
8
+ * every glyph resolves through this one module.
9
+ */
10
+ import type { FileLetter } from "../pware.oc.opencode/pware.oc.opencode.files.js"
11
+ import type { MyWorkKind } from "../pware.oc.runtime/pware.oc.runtime.mywork.js"
12
+ import type { ReviewLane, ReviewState } from "../pware.oc.omo/resolver/pware.oc.omo.resolver.plan.js"
13
+ import {
14
+ REVIEW_STATUS_APPROVED,
15
+ REVIEW_STATUS_CHANGES_REQUESTED,
16
+ REVIEW_STATUS_INCONCLUSIVE,
17
+ REVIEW_STATUS_PENDING,
18
+ ROUND_STATUS_ACTIVE,
19
+ } from "../pware.oc.omo/constants/pware.oc.omo.constants.reviewStatus.js"
20
+ import {
21
+ MY_WORK_GROUP_DISMISSED,
22
+ MY_WORK_GROUP_DRAFT_DOCS,
23
+ MY_WORK_GROUP_DRAFTING,
24
+ MY_WORK_GROUP_FINISHED,
25
+ MY_WORK_GROUP_PINNED,
26
+ MY_WORK_GROUP_PLANS,
27
+ MY_WORK_GROUP_READY_REVIEW,
28
+ MY_WORK_GROUP_READY_START,
29
+ MY_WORK_GROUP_SESSIONS,
30
+ } from "../pware.oc.core/constants/pware.oc.core.constants.myWork.js"
31
+ import {
32
+ QUESTION_KIND_ERROR,
33
+ QUESTION_KIND_INTERRUPTED,
34
+ QUESTION_KIND_QUESTION,
35
+ } from "../pware.oc.opencode/constants/pware.oc.opencode.constants.questionKind.js"
36
+ import type { GlyphSpec } from "../pware.oc.core/pware.oc.core.glyph.js"
37
+
38
+ export { workStatusGlyph } from "../pware.oc.core/pware.oc.core.status.js"
39
+ export {
40
+ SPINNER_FRAMES,
41
+ QUEUED_GLYPH,
42
+ ENGAGE_MIN_FRAMES,
43
+ ENGAGE_MAX_FRAMES,
44
+ spinnerFrame,
45
+ engageFill,
46
+ engageDone,
47
+ flowBlinkOn,
48
+ sinPulseAlpha,
49
+ type SinPulseAlphaOpts,
50
+ markTone,
51
+ stateGlyph,
52
+ directionGlyph,
53
+ defaultBodyTone,
54
+ type GlyphSpec,
55
+ type ToneKey,
56
+ } from "../pware.oc.core/pware.oc.core.glyph.js"
57
+
58
+ /** Group header before a clustered row list. */
59
+ export const GROUP_GLYPH = "▾"
60
+ /** Perf: a phase of the wall clock spent thinking. */
61
+ export const THINK_GLYPH = "∴"
62
+
63
+ /** The glyph for a My work kind — a complete spec; the tone says how urgent it is. */
64
+ export function myWorkGlyph(kind: MyWorkKind): GlyphSpec {
65
+ if (kind === QUESTION_KIND_QUESTION) return { char: "?", tone: "warning" }
66
+ if (kind === QUESTION_KIND_INTERRUPTED) return { char: "⊘", tone: "textMuted" }
67
+ if (kind === QUESTION_KIND_ERROR) return { char: "×", tone: "error" }
68
+ if (kind === MY_WORK_GROUP_SESSIONS) return { char: "◔", tone: "primary" }
69
+ if (kind === MY_WORK_GROUP_PINNED) return { char: "P", tone: "primary" }
70
+ if (kind === MY_WORK_GROUP_READY_REVIEW) return { char: "!", tone: "warning" }
71
+ if (kind === MY_WORK_GROUP_DRAFTING) return { char: "…", tone: "textMuted" }
72
+ if (kind === MY_WORK_GROUP_DRAFT_DOCS) return { char: "•", tone: "textMuted" }
73
+ if (kind === MY_WORK_GROUP_PLANS) return { char: "▸", tone: "textMuted" }
74
+ if (kind === MY_WORK_GROUP_READY_START) return { char: "▶", tone: "primary" }
75
+ if (kind === MY_WORK_GROUP_FINISHED) return { char: "✓", tone: "success" }
76
+ if (kind === MY_WORK_GROUP_DISMISSED) return { char: "⊘", tone: "textMuted" }
77
+ return { char: "!", tone: "warning" }
78
+ }
79
+
80
+ /**
81
+ * Neutral tab-header light: a small muted bullet, shown when nothing is
82
+ * waiting on the user (and for every non-My-work tab).
83
+ */
84
+ export const TAB_NEUTRAL_GLYPH: GlyphSpec = { char: "•", tone: "textMuted" }
85
+
86
+ /** One item the My-work tab light reasons about. `ended` marks a terminated part. */
87
+ export type TabAttentionItem = {
88
+ kind: MyWorkKind
89
+ /** True when the part already has a terminal end time — history, not live. */
90
+ ended?: boolean
91
+ }
92
+
93
+ /**
94
+ * The tab light's winner list, most urgent first. A live open question beats
95
+ * everything; an *ended* error is history (the panel still lists it in Errors)
96
+ * and never lights the tab; running/drafting/finished are not waiting on you.
97
+ */
98
+ const TAB_ATTENTION_PRIORITY: readonly ((i: TabAttentionItem) => boolean)[] = [
99
+ (i) => i.kind === QUESTION_KIND_QUESTION,
100
+ (i) => i.kind === QUESTION_KIND_ERROR && !i.ended,
101
+ (i) => i.kind === MY_WORK_GROUP_READY_REVIEW,
102
+ (i) => i.kind === MY_WORK_GROUP_READY_START,
103
+ (i) => i.kind === QUESTION_KIND_INTERRUPTED && !i.ended,
104
+ ]
105
+
106
+ /** The My-work tab light: the most urgent live waiting item, or a neutral bullet. */
107
+ export function tabAttentionGlyph(items: readonly TabAttentionItem[]): GlyphSpec {
108
+ for (const match of TAB_ATTENTION_PRIORITY) {
109
+ for (const item of items) {
110
+ if (match(item)) return myWorkGlyph(item.kind)
111
+ }
112
+ }
113
+ return TAB_NEUTRAL_GLYPH
114
+ }
115
+
116
+ /** A git-status letter as a glyph: added green, deleted red, modified yellow, rest muted. */
117
+ export function fileLetterGlyph(letter: FileLetter | null): GlyphSpec {
118
+ const char = letter ?? "•"
119
+ const tone =
120
+ letter === "A" ? "success" : letter === "D" ? "error" : letter === "M" ? "warning" : "textMuted"
121
+ return { char, tone }
122
+ }
123
+
124
+ /** One ulw-plan review lane: ✓ approved, ! changes, ? inconclusive, … live, · pending. */
125
+ export function reviewLaneGlyph(lane: ReviewLane | null | undefined): GlyphSpec {
126
+ const s = lane?.status
127
+ if (s === REVIEW_STATUS_APPROVED) return { char: "✓", tone: "success" }
128
+ if (s === REVIEW_STATUS_CHANGES_REQUESTED) return { char: "!", tone: "warning" }
129
+ if (s === REVIEW_STATUS_INCONCLUSIVE) return { char: "?", tone: "warning" }
130
+ if (s === REVIEW_STATUS_PENDING || !s) return { char: "·", tone: "textMuted" }
131
+ return { char: "…", tone: "textMuted" }
132
+ }
133
+
134
+ /**
135
+ * Compact review state for a plan row: `R<round> <momus><independent>` while a
136
+ * round is recorded, otherwise just the two lanes. Null when no review exists.
137
+ */
138
+ export function reviewStateSuffix(review: ReviewState | null | undefined): string | null {
139
+ if (!review || (!review.required && !review.roundId && !review.roundStatus)) return null
140
+ const lanes = `${reviewLaneGlyph(review.lanes.momus).char}${reviewLaneGlyph(review.lanes.independent).char}`
141
+ if (review.roundId) return `R${review.roundId} ${lanes}`
142
+ if (review.roundStatus === ROUND_STATUS_ACTIVE) return `R… ${lanes}`
143
+ return lanes
144
+ }
@@ -1,111 +1,111 @@
1
- import type { TuiKeymap, TuiPluginApi } from "@opencode-ai/plugin/tui"
2
- import { profileAsync } from "../pware.oc.core/pware.oc.core.debug.js"
3
- import { PART_TYPE_TEXT } from "../pware.oc.core/constants/pware.oc.core.constants.partType.js"
4
- import {
5
- START_WORK_MAKE_PR,
6
- START_WORK_SHIP,
7
- } from "../pware.oc.omo/constants/pware.oc.omo.constants.startWork.js"
8
- import { startWorkCommand, type StartWorkMode } from "../pware.oc.runtime/pware.oc.runtime.mywork.js"
9
-
10
- export function selectSession(api: TuiPluginApi, sessionId: string | null | undefined): void {
11
- if (!sessionId) return
12
- const tui = (api as TuiPluginApi & {
13
- client?: {
14
- tui?: {
15
- selectSession?: (arg: unknown) => Promise<unknown> | unknown
16
- publish?: (arg: unknown) => Promise<unknown> | unknown
17
- }
18
- }
19
- }).client?.tui
20
- if (!tui) return
21
- const go = async () => {
22
- try {
23
- if (typeof tui.selectSession === "function") {
24
- await tui.selectSession({ sessionID: sessionId })
25
- return
26
- }
27
- } catch {
28
- try {
29
- await tui.selectSession?.(sessionId)
30
- return
31
- } catch {
32
- }
33
- }
34
- try {
35
- await tui.publish?.({
36
- type: "tui.session.select",
37
- properties: { sessionID: sessionId },
38
- })
39
- } catch {
40
- }
41
- }
42
- void profileAsync("rpc.selectSession", go)
43
- }
44
-
45
- export function openSessionSwitcher(api: TuiPluginApi): void {
46
- try {
47
- const dispatch = (api.keymap as TuiKeymap & { dispatchCommand?: (name: string) => void })
48
- .dispatchCommand
49
- if (typeof dispatch === "function") {
50
- dispatch("session.list")
51
- return
52
- }
53
- } catch {
54
- }
55
- try {
56
- api.command?.show()
57
- } catch {
58
- }
59
- }
60
-
61
- export function openNewSessionPrompt(api: TuiPluginApi): void {
62
- try {
63
- api.route.navigate("home")
64
- } catch {
65
- }
66
- }
67
-
68
- export function runStartWork(
69
- api: TuiPluginApi,
70
- sessionId: string,
71
- mode: StartWorkMode,
72
- planName: string,
73
- ): void {
74
- const client = api.client
75
- const text = startWorkCommand(mode, planName)
76
- const flag = mode === START_WORK_MAKE_PR ? "--make-pr" : mode === START_WORK_SHIP ? "--ship" : ""
77
- const args = [planName, flag].map((s) => s.trim()).filter(Boolean).join(" ") || ""
78
- const go = async () => {
79
- try {
80
- const res = await client.session.command({
81
- sessionID: sessionId,
82
- command: "start-work",
83
- arguments: args,
84
- })
85
- if (res && !res.error) return
86
- } catch {
87
- }
88
- try {
89
- await client.session.promptAsync({
90
- sessionID: sessionId,
91
- parts: [{ type: PART_TYPE_TEXT, text }],
92
- })
93
- } catch {
94
- }
95
- }
96
- void profileAsync("rpc.startWork", go)
97
- }
98
-
99
- export function approvePlan(api: TuiPluginApi, sessionId: string): void {
100
- const client = api.client
101
- const go = async () => {
102
- try {
103
- await client.session.promptAsync({
104
- sessionID: sessionId,
105
- parts: [{ type: PART_TYPE_TEXT, text: "ok" }],
106
- })
107
- } catch {
108
- }
109
- }
110
- void profileAsync("rpc.approve", go)
111
- }
1
+ import type { TuiKeymap, TuiPluginApi } from "@opencode-ai/plugin/tui"
2
+ import { profileAsync } from "../pware.oc.core/pware.oc.core.debug.js"
3
+ import { PART_TYPE_TEXT } from "../pware.oc.core/constants/pware.oc.core.constants.partType.js"
4
+ import {
5
+ START_WORK_MAKE_PR,
6
+ START_WORK_SHIP,
7
+ } from "../pware.oc.omo/constants/pware.oc.omo.constants.startWork.js"
8
+ import { startWorkCommand, type StartWorkMode } from "../pware.oc.runtime/pware.oc.runtime.mywork.js"
9
+
10
+ export function selectSession(api: TuiPluginApi, sessionId: string | null | undefined): void {
11
+ if (!sessionId) return
12
+ const tui = (api as TuiPluginApi & {
13
+ client?: {
14
+ tui?: {
15
+ selectSession?: (arg: unknown) => Promise<unknown> | unknown
16
+ publish?: (arg: unknown) => Promise<unknown> | unknown
17
+ }
18
+ }
19
+ }).client?.tui
20
+ if (!tui) return
21
+ const go = async () => {
22
+ try {
23
+ if (typeof tui.selectSession === "function") {
24
+ await tui.selectSession({ sessionID: sessionId })
25
+ return
26
+ }
27
+ } catch {
28
+ try {
29
+ await tui.selectSession?.(sessionId)
30
+ return
31
+ } catch {
32
+ }
33
+ }
34
+ try {
35
+ await tui.publish?.({
36
+ type: "tui.session.select",
37
+ properties: { sessionID: sessionId },
38
+ })
39
+ } catch {
40
+ }
41
+ }
42
+ void profileAsync("rpc.selectSession", go)
43
+ }
44
+
45
+ export function openSessionSwitcher(api: TuiPluginApi): void {
46
+ try {
47
+ const dispatch = (api.keymap as TuiKeymap & { dispatchCommand?: (name: string) => void })
48
+ .dispatchCommand
49
+ if (typeof dispatch === "function") {
50
+ dispatch("session.list")
51
+ return
52
+ }
53
+ } catch {
54
+ }
55
+ try {
56
+ api.command?.show()
57
+ } catch {
58
+ }
59
+ }
60
+
61
+ export function openNewSessionPrompt(api: TuiPluginApi): void {
62
+ try {
63
+ api.route.navigate("home")
64
+ } catch {
65
+ }
66
+ }
67
+
68
+ export function runStartWork(
69
+ api: TuiPluginApi,
70
+ sessionId: string,
71
+ mode: StartWorkMode,
72
+ planName: string,
73
+ ): void {
74
+ const client = api.client
75
+ const text = startWorkCommand(mode, planName)
76
+ const flag = mode === START_WORK_MAKE_PR ? "--make-pr" : mode === START_WORK_SHIP ? "--ship" : ""
77
+ const args = [planName, flag].map((s) => s.trim()).filter(Boolean).join(" ") || ""
78
+ const go = async () => {
79
+ try {
80
+ const res = await client.session.command({
81
+ sessionID: sessionId,
82
+ command: "start-work",
83
+ arguments: args,
84
+ })
85
+ if (res && !res.error) return
86
+ } catch {
87
+ }
88
+ try {
89
+ await client.session.promptAsync({
90
+ sessionID: sessionId,
91
+ parts: [{ type: PART_TYPE_TEXT, text }],
92
+ })
93
+ } catch {
94
+ }
95
+ }
96
+ void profileAsync("rpc.startWork", go)
97
+ }
98
+
99
+ export function approvePlan(api: TuiPluginApi, sessionId: string): void {
100
+ const client = api.client
101
+ const go = async () => {
102
+ try {
103
+ await client.session.promptAsync({
104
+ sessionID: sessionId,
105
+ parts: [{ type: PART_TYPE_TEXT, text: "ok" }],
106
+ })
107
+ } catch {
108
+ }
109
+ }
110
+ void profileAsync("rpc.approve", go)
111
+ }