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.
- package/.oesignore +17 -17
- package/CHANGELOG.md +96 -95
- package/LICENSE +21 -21
- package/README.md +150 -235
- package/oes.json +13 -11
- package/package.json +100 -100
- package/scripts/install-git-hooks.mjs +29 -29
- package/src/pware.oc.core/constants/index.ts +18 -18
- package/src/pware.oc.core/constants/pware.oc.core.constants.eventKind.ts +29 -29
- package/src/pware.oc.core/constants/pware.oc.core.constants.eventName.ts +15 -13
- package/src/pware.oc.core/constants/pware.oc.core.constants.eventType.ts +241 -241
- package/src/pware.oc.core/constants/pware.oc.core.constants.myWork.ts +55 -55
- package/src/pware.oc.core/constants/pware.oc.core.constants.partType.ts +65 -65
- package/src/pware.oc.core/constants/pware.oc.core.constants.phase.ts +58 -58
- package/src/pware.oc.core/constants/pware.oc.core.constants.pulse.ts +63 -63
- package/src/pware.oc.core/constants/pware.oc.core.constants.rowKind.ts +34 -34
- package/src/pware.oc.core/constants/pware.oc.core.constants.status.ts +74 -74
- package/src/pware.oc.core/constants/pware.oc.core.constants.toolName.ts +69 -69
- package/src/pware.oc.core/git/index.ts +7 -7
- package/src/pware.oc.core/git/pware.oc.core.git.ts +237 -237
- package/src/pware.oc.core/git/pware.oc.core.gitignore.ts +87 -87
- package/src/pware.oc.core/index.ts +19 -18
- package/src/pware.oc.core/pware.oc.core.bus.ts +42 -42
- package/src/pware.oc.core/pware.oc.core.cache.ts +48 -48
- package/src/pware.oc.core/pware.oc.core.clipboard.ts +97 -97
- package/src/pware.oc.core/pware.oc.core.debug.ts +280 -280
- package/src/pware.oc.core/pware.oc.core.events.ts +79 -79
- package/src/pware.oc.core/pware.oc.core.glyph.ts +135 -135
- package/src/pware.oc.core/pware.oc.core.layout.ts +234 -234
- package/src/pware.oc.core/pware.oc.core.oes.ts +99 -89
- package/src/pware.oc.core/pware.oc.core.paths.ts +240 -240
- package/src/pware.oc.core/pware.oc.core.preview.ts +74 -74
- package/src/pware.oc.core/pware.oc.core.pulse.ts +726 -726
- package/src/pware.oc.core/pware.oc.core.runtimeConfig.ts +41 -0
- package/src/pware.oc.core/pware.oc.core.sqlite.ts +164 -175
- package/src/pware.oc.core/pware.oc.core.sqliteGateway.ts +89 -0
- package/src/pware.oc.core/pware.oc.core.status.ts +214 -214
- package/src/pware.oc.core/pware.oc.core.timing.ts +63 -63
- package/src/pware.oc.core/pware.oc.core.width.ts +215 -215
- package/src/pware.oc.omo/constants/index.ts +15 -15
- package/src/pware.oc.omo/constants/pware.oc.omo.constants.backgroundTask.ts +18 -18
- package/src/pware.oc.omo/constants/pware.oc.omo.constants.boulderStatus.ts +49 -49
- package/src/pware.oc.omo/constants/pware.oc.omo.constants.docKind.ts +29 -29
- package/src/pware.oc.omo/constants/pware.oc.omo.constants.eventName.ts +11 -11
- package/src/pware.oc.omo/constants/pware.oc.omo.constants.planStatus.ts +60 -60
- package/src/pware.oc.omo/constants/pware.oc.omo.constants.reviewStatus.ts +49 -49
- package/src/pware.oc.omo/constants/pware.oc.omo.constants.startWork.ts +25 -25
- package/src/pware.oc.omo/constants/pware.oc.omo.constants.verdict.ts +38 -38
- package/src/pware.oc.omo/index.ts +7 -7
- package/src/pware.oc.omo/resolver/index.ts +19 -19
- package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.approval.ts +179 -179
- package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.approvalGroup.ts +116 -116
- package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.approvalState.ts +34 -34
- package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.boulder.ts +503 -503
- package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.config.ts +40 -40
- package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.doc.ts +269 -269
- package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.draftFile.ts +18 -18
- package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.notepadsFile.ts +18 -18
- package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.plan.ts +155 -155
- package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.planFile.ts +363 -361
- package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.proofFile.ts +18 -18
- package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.rulesFile.ts +11 -11
- package/src/pware.oc.omo/resolver/pware.oc.omo.resolver.runContinuationFile.ts +14 -14
- package/src/pware.oc.opencode/constants/index.ts +10 -10
- package/src/pware.oc.opencode/constants/pware.oc.opencode.constants.eventName.ts +15 -15
- package/src/pware.oc.opencode/constants/pware.oc.opencode.constants.fileTouch.ts +18 -18
- package/src/pware.oc.opencode/constants/pware.oc.opencode.constants.questionKind.ts +45 -45
- package/src/pware.oc.opencode/constants/pware.oc.opencode.constants.sessionStatus.ts +58 -58
- package/src/pware.oc.opencode/index.ts +8 -8
- package/src/pware.oc.opencode/pware.oc.opencode.events.ts +182 -182
- package/src/pware.oc.opencode/pware.oc.opencode.files.ts +399 -399
- package/src/pware.oc.opencode/resolver/index.ts +223 -170
- package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.file.ts +150 -162
- package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.question.ts +149 -185
- package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.session.ts +248 -211
- package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.todo.ts +22 -26
- package/src/pware.oc.opencode/resolver/pware.oc.opencode.resolver.tool.ts +224 -236
- package/src/pware.oc.perf/index.ts +14 -14
- package/src/pware.oc.perf/pware.oc.perf.asciichart.d.ts +15 -15
- package/src/pware.oc.perf/pware.oc.perf.charts.ts +284 -284
- package/src/pware.oc.perf/pware.oc.perf.reader.ts +962 -927
- package/src/pware.oc.perf/pware.oc.perf.realtime.ts +88 -88
- package/src/pware.oc.perf/pware.oc.perf.realtimeBlock.ts +118 -118
- package/src/pware.oc.perf/pware.oc.perf.realtimeCpuRam.ts +79 -79
- package/src/pware.oc.perf/pware.oc.perf.realtimeSampler.ts +71 -71
- package/src/pware.oc.perf/pware.oc.perf.realtimeTimeline.ts +214 -214
- package/src/pware.oc.perf/pware.oc.perf.self.ts +179 -179
- package/src/pware.oc.perf/pware.oc.perf.view.tsx +463 -462
- package/src/pware.oc.runtime/index.ts +13 -13
- package/src/pware.oc.runtime/pware.oc.runtime.monitor.ts +142 -142
- package/src/pware.oc.runtime/pware.oc.runtime.mywork-enrich.ts +87 -79
- package/src/pware.oc.runtime/pware.oc.runtime.mywork.ts +282 -253
- package/src/pware.oc.runtime/pware.oc.runtime.omoRead.ts +37 -0
- package/src/pware.oc.runtime/pware.oc.runtime.questions.ts +83 -95
- package/src/pware.oc.runtime/pware.oc.runtime.snapshotClient.ts +130 -129
- package/src/pware.oc.runtime/pware.oc.runtime.source.ts +105 -105
- package/src/pware.oc.runtime/pware.oc.runtime.worker.ts +44 -43
- package/src/pware.oc.runtime/resolver/index.ts +268 -224
- package/src/pware.oc.runtime/resolver/pware.oc.runtime.resolver.delegate.ts +146 -146
- package/src/pware.oc.ui/index.ts +12 -12
- package/src/pware.oc.ui/pware.oc.ui.chrome.tsx +381 -339
- package/src/pware.oc.ui/pware.oc.ui.glyphs.tsx +144 -144
- package/src/pware.oc.ui/pware.oc.ui.host.tsx +111 -111
- package/src/pware.oc.ui/pware.oc.ui.live.tsx +82 -82
- package/src/pware.oc.ui/pware.oc.ui.menudialogs.tsx +843 -843
- package/src/pware.oc.ui/pware.oc.ui.sections.tsx +552 -526
- package/src/pware.oc.ui/pware.oc.ui.sidebar.tsx +1718 -1629
- package/src/pware.oc.ui.tsx +98 -98
|
@@ -1,253 +1,282 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* pware.oc.core.mywork.resolver
|
|
3
|
-
*
|
|
4
|
-
* The "My work" queue — one list of things awaiting the user's action, from
|
|
5
|
-
* two sources: an open OpenCode `question` (core, always) and an OMO plan
|
|
6
|
-
* awaiting approval (optional, only when `.omo/` is present).
|
|
7
|
-
*/
|
|
8
|
-
import type { OpenQuestion } from "../pware.oc.opencode/resolver/pware.oc.opencode.resolver.question.js"
|
|
9
|
-
import type {
|
|
10
|
-
AgentStatus,
|
|
11
|
-
SessionActivityState,
|
|
12
|
-
} from "../pware.oc.opencode/resolver/pware.oc.opencode.resolver.session.js"
|
|
13
|
-
import type { ReviewState } from "../pware.oc.omo/resolver/pware.oc.omo.resolver.plan.js"
|
|
14
|
-
import type { EnrichedApproval } from "./pware.oc.runtime.mywork-enrich.js"
|
|
15
|
-
import {
|
|
16
|
-
MY_WORK_GROUP_DISMISSED,
|
|
17
|
-
MY_WORK_GROUP_DRAFT_DOCS,
|
|
18
|
-
MY_WORK_GROUP_DRAFTING,
|
|
19
|
-
MY_WORK_GROUP_FINISHED,
|
|
20
|
-
MY_WORK_GROUP_PINNED,
|
|
21
|
-
MY_WORK_GROUP_PLANS,
|
|
22
|
-
MY_WORK_GROUP_READY_REVIEW,
|
|
23
|
-
MY_WORK_GROUP_READY_START,
|
|
24
|
-
MY_WORK_GROUP_SESSIONS,
|
|
25
|
-
type ApprovalGroupKind,
|
|
26
|
-
} from "../pware.oc.core/constants/pware.oc.core.constants.myWork.js"
|
|
27
|
-
import { isDraftOf, resolveApprovalGroup } from "../pware.oc.omo/resolver/pware.oc.omo.resolver.approvalGroup.js"
|
|
28
|
-
import {
|
|
29
|
-
QUESTION_KIND_ERROR,
|
|
30
|
-
QUESTION_KIND_INTERRUPTED,
|
|
31
|
-
QUESTION_KIND_QUESTION,
|
|
32
|
-
type OpenQuestionKind,
|
|
33
|
-
} from "../pware.oc.opencode/constants/pware.oc.opencode.constants.questionKind.js"
|
|
34
|
-
import {
|
|
35
|
-
START_WORK_MAKE_PR,
|
|
36
|
-
START_WORK_PLAIN,
|
|
37
|
-
START_WORK_SHIP,
|
|
38
|
-
type StartWorkMode,
|
|
39
|
-
} from "../pware.oc.omo/constants/pware.oc.omo.constants.startWork.js"
|
|
40
|
-
|
|
41
|
-
export type { ApprovalGroupKind, OpenQuestionKind, StartWorkMode }
|
|
42
|
-
|
|
43
|
-
export type QuestionGroupKind = OpenQuestionKind | typeof MY_WORK_GROUP_DISMISSED
|
|
44
|
-
|
|
45
|
-
export type MyWorkItem =
|
|
46
|
-
| {
|
|
47
|
-
kind: QuestionGroupKind
|
|
48
|
-
partId: string
|
|
49
|
-
sessionId: string
|
|
50
|
-
title: string
|
|
51
|
-
startedAt: number | null
|
|
52
|
-
/** `state.error` text for interrupted/error rows; null for an open question. */
|
|
53
|
-
reason: string | null
|
|
54
|
-
}
|
|
55
|
-
| {
|
|
56
|
-
kind: ApprovalGroupKind
|
|
57
|
-
name: string
|
|
58
|
-
rel: string
|
|
59
|
-
pendingAction: string | null
|
|
60
|
-
updatedAt: number | null
|
|
61
|
-
sessionState: SessionActivityState | null
|
|
62
|
-
review: ReviewState | null
|
|
63
|
-
}
|
|
64
|
-
| {
|
|
65
|
-
kind: typeof MY_WORK_GROUP_SESSIONS
|
|
66
|
-
sessionId: string
|
|
67
|
-
title: string
|
|
68
|
-
status: AgentStatus
|
|
69
|
-
timeUpdated: number | null
|
|
70
|
-
}
|
|
71
|
-
| {
|
|
72
|
-
kind: typeof MY_WORK_GROUP_PINNED
|
|
73
|
-
sessionId: string
|
|
74
|
-
title: string
|
|
75
|
-
status: AgentStatus
|
|
76
|
-
timeUpdated: number | null
|
|
77
|
-
}
|
|
78
|
-
| {
|
|
79
|
-
kind: typeof MY_WORK_GROUP_DRAFT_DOCS
|
|
80
|
-
name: string
|
|
81
|
-
rel: string
|
|
82
|
-
updatedAt: number | null
|
|
83
|
-
}
|
|
84
|
-
| {
|
|
85
|
-
kind: typeof MY_WORK_GROUP_PLANS
|
|
86
|
-
name: string
|
|
87
|
-
rel: string
|
|
88
|
-
updatedAt: number | null
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export type MyWorkKind = MyWorkItem["kind"]
|
|
92
|
-
|
|
93
|
-
export const MY_WORK_ORDER: readonly MyWorkKind[] = [
|
|
94
|
-
MY_WORK_GROUP_PINNED,
|
|
95
|
-
QUESTION_KIND_QUESTION,
|
|
96
|
-
QUESTION_KIND_INTERRUPTED,
|
|
97
|
-
QUESTION_KIND_ERROR,
|
|
98
|
-
MY_WORK_GROUP_SESSIONS,
|
|
99
|
-
MY_WORK_GROUP_READY_REVIEW,
|
|
100
|
-
MY_WORK_GROUP_READY_START,
|
|
101
|
-
MY_WORK_GROUP_FINISHED,
|
|
102
|
-
MY_WORK_GROUP_DRAFTING,
|
|
103
|
-
MY_WORK_GROUP_DRAFT_DOCS,
|
|
104
|
-
MY_WORK_GROUP_PLANS,
|
|
105
|
-
MY_WORK_GROUP_DISMISSED,
|
|
106
|
-
]
|
|
107
|
-
|
|
108
|
-
const MY_WORK_LABELS: Record<MyWorkKind, string> = {
|
|
109
|
-
[MY_WORK_GROUP_PINNED]: "Pinned",
|
|
110
|
-
[QUESTION_KIND_QUESTION]: "Awaiting answer",
|
|
111
|
-
[QUESTION_KIND_INTERRUPTED]: "Interrupted",
|
|
112
|
-
[QUESTION_KIND_ERROR]: "Errors",
|
|
113
|
-
[MY_WORK_GROUP_SESSIONS]: "Sessions",
|
|
114
|
-
[MY_WORK_GROUP_READY_REVIEW]: "Ready to review",
|
|
115
|
-
[MY_WORK_GROUP_READY_START]: "Ready to start",
|
|
116
|
-
[MY_WORK_GROUP_FINISHED]: "Finished",
|
|
117
|
-
[MY_WORK_GROUP_DISMISSED]: "Dismissed questions",
|
|
118
|
-
[MY_WORK_GROUP_DRAFTING]: "Drafting",
|
|
119
|
-
[MY_WORK_GROUP_DRAFT_DOCS]: "Draft docs",
|
|
120
|
-
[MY_WORK_GROUP_PLANS]: "Plans",
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export function myWorkLabel(kind: MyWorkKind): string {
|
|
124
|
-
return MY_WORK_LABELS[kind]
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Why "Navigate to session" is unavailable for an approval: no writer session
|
|
129
|
-
* was found in the database, or the database itself could not be opened. Null
|
|
130
|
-
* when navigation is actionable.
|
|
131
|
-
*/
|
|
132
|
-
export function approvalContinueHint(
|
|
133
|
-
sessionId: string | null | undefined,
|
|
134
|
-
dbAvailable: boolean,
|
|
135
|
-
): string | null {
|
|
136
|
-
if (sessionId) return null
|
|
137
|
-
return dbAvailable ? "No session wrote this plan" : "Database unavailable"
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/** The exact "start work" command text for a delivery mode and optional plan name. */
|
|
141
|
-
export function startWorkCommand(mode: StartWorkMode, planName?: string | null): string {
|
|
142
|
-
const name = typeof planName === "string" ? planName.trim() : ""
|
|
143
|
-
const base = name ? `start work ${name}` : "start work"
|
|
144
|
-
if (mode === START_WORK_MAKE_PR) return `${base} --make-pr`
|
|
145
|
-
if (mode === START_WORK_SHIP) return `${base} --ship`
|
|
146
|
-
return base
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
1
|
+
/**
|
|
2
|
+
* pware.oc.core.mywork.resolver
|
|
3
|
+
*
|
|
4
|
+
* The "My work" queue — one list of things awaiting the user's action, from
|
|
5
|
+
* two sources: an open OpenCode `question` (core, always) and an OMO plan
|
|
6
|
+
* awaiting approval (optional, only when `.omo/` is present).
|
|
7
|
+
*/
|
|
8
|
+
import type { OpenQuestion } from "../pware.oc.opencode/resolver/pware.oc.opencode.resolver.question.js"
|
|
9
|
+
import type {
|
|
10
|
+
AgentStatus,
|
|
11
|
+
SessionActivityState,
|
|
12
|
+
} from "../pware.oc.opencode/resolver/pware.oc.opencode.resolver.session.js"
|
|
13
|
+
import type { ReviewState } from "../pware.oc.omo/resolver/pware.oc.omo.resolver.plan.js"
|
|
14
|
+
import type { EnrichedApproval } from "./pware.oc.runtime.mywork-enrich.js"
|
|
15
|
+
import {
|
|
16
|
+
MY_WORK_GROUP_DISMISSED,
|
|
17
|
+
MY_WORK_GROUP_DRAFT_DOCS,
|
|
18
|
+
MY_WORK_GROUP_DRAFTING,
|
|
19
|
+
MY_WORK_GROUP_FINISHED,
|
|
20
|
+
MY_WORK_GROUP_PINNED,
|
|
21
|
+
MY_WORK_GROUP_PLANS,
|
|
22
|
+
MY_WORK_GROUP_READY_REVIEW,
|
|
23
|
+
MY_WORK_GROUP_READY_START,
|
|
24
|
+
MY_WORK_GROUP_SESSIONS,
|
|
25
|
+
type ApprovalGroupKind,
|
|
26
|
+
} from "../pware.oc.core/constants/pware.oc.core.constants.myWork.js"
|
|
27
|
+
import { isDraftOf, resolveApprovalGroup } from "../pware.oc.omo/resolver/pware.oc.omo.resolver.approvalGroup.js"
|
|
28
|
+
import {
|
|
29
|
+
QUESTION_KIND_ERROR,
|
|
30
|
+
QUESTION_KIND_INTERRUPTED,
|
|
31
|
+
QUESTION_KIND_QUESTION,
|
|
32
|
+
type OpenQuestionKind,
|
|
33
|
+
} from "../pware.oc.opencode/constants/pware.oc.opencode.constants.questionKind.js"
|
|
34
|
+
import {
|
|
35
|
+
START_WORK_MAKE_PR,
|
|
36
|
+
START_WORK_PLAIN,
|
|
37
|
+
START_WORK_SHIP,
|
|
38
|
+
type StartWorkMode,
|
|
39
|
+
} from "../pware.oc.omo/constants/pware.oc.omo.constants.startWork.js"
|
|
40
|
+
|
|
41
|
+
export type { ApprovalGroupKind, OpenQuestionKind, StartWorkMode }
|
|
42
|
+
|
|
43
|
+
export type QuestionGroupKind = OpenQuestionKind | typeof MY_WORK_GROUP_DISMISSED
|
|
44
|
+
|
|
45
|
+
export type MyWorkItem =
|
|
46
|
+
| {
|
|
47
|
+
kind: QuestionGroupKind
|
|
48
|
+
partId: string
|
|
49
|
+
sessionId: string
|
|
50
|
+
title: string
|
|
51
|
+
startedAt: number | null
|
|
52
|
+
/** `state.error` text for interrupted/error rows; null for an open question. */
|
|
53
|
+
reason: string | null
|
|
54
|
+
}
|
|
55
|
+
| {
|
|
56
|
+
kind: ApprovalGroupKind
|
|
57
|
+
name: string
|
|
58
|
+
rel: string
|
|
59
|
+
pendingAction: string | null
|
|
60
|
+
updatedAt: number | null
|
|
61
|
+
sessionState: SessionActivityState | null
|
|
62
|
+
review: ReviewState | null
|
|
63
|
+
}
|
|
64
|
+
| {
|
|
65
|
+
kind: typeof MY_WORK_GROUP_SESSIONS
|
|
66
|
+
sessionId: string
|
|
67
|
+
title: string
|
|
68
|
+
status: AgentStatus
|
|
69
|
+
timeUpdated: number | null
|
|
70
|
+
}
|
|
71
|
+
| {
|
|
72
|
+
kind: typeof MY_WORK_GROUP_PINNED
|
|
73
|
+
sessionId: string
|
|
74
|
+
title: string
|
|
75
|
+
status: AgentStatus
|
|
76
|
+
timeUpdated: number | null
|
|
77
|
+
}
|
|
78
|
+
| {
|
|
79
|
+
kind: typeof MY_WORK_GROUP_DRAFT_DOCS
|
|
80
|
+
name: string
|
|
81
|
+
rel: string
|
|
82
|
+
updatedAt: number | null
|
|
83
|
+
}
|
|
84
|
+
| {
|
|
85
|
+
kind: typeof MY_WORK_GROUP_PLANS
|
|
86
|
+
name: string
|
|
87
|
+
rel: string
|
|
88
|
+
updatedAt: number | null
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export type MyWorkKind = MyWorkItem["kind"]
|
|
92
|
+
|
|
93
|
+
export const MY_WORK_ORDER: readonly MyWorkKind[] = [
|
|
94
|
+
MY_WORK_GROUP_PINNED,
|
|
95
|
+
QUESTION_KIND_QUESTION,
|
|
96
|
+
QUESTION_KIND_INTERRUPTED,
|
|
97
|
+
QUESTION_KIND_ERROR,
|
|
98
|
+
MY_WORK_GROUP_SESSIONS,
|
|
99
|
+
MY_WORK_GROUP_READY_REVIEW,
|
|
100
|
+
MY_WORK_GROUP_READY_START,
|
|
101
|
+
MY_WORK_GROUP_FINISHED,
|
|
102
|
+
MY_WORK_GROUP_DRAFTING,
|
|
103
|
+
MY_WORK_GROUP_DRAFT_DOCS,
|
|
104
|
+
MY_WORK_GROUP_PLANS,
|
|
105
|
+
MY_WORK_GROUP_DISMISSED,
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
const MY_WORK_LABELS: Record<MyWorkKind, string> = {
|
|
109
|
+
[MY_WORK_GROUP_PINNED]: "Pinned",
|
|
110
|
+
[QUESTION_KIND_QUESTION]: "Awaiting answer",
|
|
111
|
+
[QUESTION_KIND_INTERRUPTED]: "Interrupted",
|
|
112
|
+
[QUESTION_KIND_ERROR]: "Errors",
|
|
113
|
+
[MY_WORK_GROUP_SESSIONS]: "Sessions",
|
|
114
|
+
[MY_WORK_GROUP_READY_REVIEW]: "Ready to review",
|
|
115
|
+
[MY_WORK_GROUP_READY_START]: "Ready to start",
|
|
116
|
+
[MY_WORK_GROUP_FINISHED]: "Finished",
|
|
117
|
+
[MY_WORK_GROUP_DISMISSED]: "Dismissed questions",
|
|
118
|
+
[MY_WORK_GROUP_DRAFTING]: "Drafting",
|
|
119
|
+
[MY_WORK_GROUP_DRAFT_DOCS]: "Draft docs",
|
|
120
|
+
[MY_WORK_GROUP_PLANS]: "Plans",
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function myWorkLabel(kind: MyWorkKind): string {
|
|
124
|
+
return MY_WORK_LABELS[kind]
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Why "Navigate to session" is unavailable for an approval: no writer session
|
|
129
|
+
* was found in the database, or the database itself could not be opened. Null
|
|
130
|
+
* when navigation is actionable.
|
|
131
|
+
*/
|
|
132
|
+
export function approvalContinueHint(
|
|
133
|
+
sessionId: string | null | undefined,
|
|
134
|
+
dbAvailable: boolean,
|
|
135
|
+
): string | null {
|
|
136
|
+
if (sessionId) return null
|
|
137
|
+
return dbAvailable ? "No session wrote this plan" : "Database unavailable"
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** The exact "start work" command text for a delivery mode and optional plan name. */
|
|
141
|
+
export function startWorkCommand(mode: StartWorkMode, planName?: string | null): string {
|
|
142
|
+
const name = typeof planName === "string" ? planName.trim() : ""
|
|
143
|
+
const base = name ? `start work ${name}` : "start work"
|
|
144
|
+
if (mode === START_WORK_MAKE_PR) return `${base} --make-pr`
|
|
145
|
+
if (mode === START_WORK_SHIP) return `${base} --ship`
|
|
146
|
+
return base
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Group the My work queue. Pinned always leads — even when empty — as a placeholder. */
|
|
150
|
+
export function groupMyWork(
|
|
151
|
+
items: readonly MyWorkItem[],
|
|
152
|
+
): { kind: MyWorkKind; items: MyWorkItem[] }[] {
|
|
153
|
+
const out: { kind: MyWorkKind; items: MyWorkItem[] }[] = []
|
|
154
|
+
out.push({ kind: MY_WORK_GROUP_PINNED, items: items.filter((i) => i.kind === MY_WORK_GROUP_PINNED) })
|
|
155
|
+
for (const kind of MY_WORK_ORDER) {
|
|
156
|
+
if (kind === MY_WORK_GROUP_PINNED) continue
|
|
157
|
+
const bucket = items.filter((i) => i.kind === kind)
|
|
158
|
+
if (bucket.length > 0) out.push({ kind, items: bucket })
|
|
159
|
+
}
|
|
160
|
+
return out
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Build the question items from an open-question read (title comes from the row). */
|
|
164
|
+
export function toQuestionItems(questions: readonly OpenQuestion[]): MyWorkItem[] {
|
|
165
|
+
return questions.map((q) => ({
|
|
166
|
+
kind: q.kind,
|
|
167
|
+
partId: q.partId,
|
|
168
|
+
sessionId: q.sessionId,
|
|
169
|
+
title: q.title,
|
|
170
|
+
startedAt: q.startedAt,
|
|
171
|
+
reason: q.reason,
|
|
172
|
+
}))
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/** Build the approval items from a pending-approval read, dropping superseded plans. */
|
|
176
|
+
export function toApprovalItems(approvals: readonly EnrichedApproval[]): MyWorkItem[] {
|
|
177
|
+
const out: MyWorkItem[] = []
|
|
178
|
+
for (const a of approvals) {
|
|
179
|
+
const kind = resolveApprovalGroup(a.status, isDraftOf(a.rel), a.workState, a.todosDone)
|
|
180
|
+
if (!kind) continue
|
|
181
|
+
out.push({
|
|
182
|
+
kind,
|
|
183
|
+
name: a.name,
|
|
184
|
+
rel: a.rel,
|
|
185
|
+
pendingAction: a.pendingAction,
|
|
186
|
+
updatedAt: a.updatedAt,
|
|
187
|
+
sessionState: a.sessionState,
|
|
188
|
+
review: a.review,
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
return out
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** Build the Draft docs items — drafts no action group covers, browsed as files. */
|
|
195
|
+
export function toDraftDocItems(
|
|
196
|
+
docs: readonly { name: string; rel: string; updatedAt: number | null }[],
|
|
197
|
+
): MyWorkItem[] {
|
|
198
|
+
return docs.map((d) => ({ kind: MY_WORK_GROUP_DRAFT_DOCS, name: d.name, rel: d.rel, updatedAt: d.updatedAt }))
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** Build the Plans items — plan files no action group covers, browsed as files. */
|
|
202
|
+
export function toPlanItems(
|
|
203
|
+
docs: readonly { name: string; rel: string; updatedAt: number | null }[],
|
|
204
|
+
): MyWorkItem[] {
|
|
205
|
+
return docs.map((d) => ({ kind: MY_WORK_GROUP_PLANS, name: d.name, rel: d.rel, updatedAt: d.updatedAt }))
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** Build the sessions group from recent main sessions — every session, live or idle. */
|
|
209
|
+
export function toSessionItems(
|
|
210
|
+
sessions: readonly {
|
|
211
|
+
id: string
|
|
212
|
+
title: string
|
|
213
|
+
status: AgentStatus
|
|
214
|
+
timeUpdated: number | null
|
|
215
|
+
}[],
|
|
216
|
+
): MyWorkItem[] {
|
|
217
|
+
return sessions.map((s) => ({
|
|
218
|
+
kind: MY_WORK_GROUP_SESSIONS,
|
|
219
|
+
sessionId: s.id,
|
|
220
|
+
title: s.title,
|
|
221
|
+
status: s.status,
|
|
222
|
+
timeUpdated: s.timeUpdated,
|
|
223
|
+
}))
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** Build pinned items from pinned session ids joined to their recent-session rows, in pin order; ids missing from `recent` are skipped. */
|
|
227
|
+
export function toPinnedItems(
|
|
228
|
+
pinnedIds: readonly string[],
|
|
229
|
+
recent: readonly {
|
|
230
|
+
id: string
|
|
231
|
+
title: string
|
|
232
|
+
status: AgentStatus
|
|
233
|
+
timeUpdated: number | null
|
|
234
|
+
}[],
|
|
235
|
+
): MyWorkItem[] {
|
|
236
|
+
const byId = new Map(recent.map((s) => [s.id, s] as const))
|
|
237
|
+
const out: MyWorkItem[] = []
|
|
238
|
+
for (const id of pinnedIds) {
|
|
239
|
+
const s = byId.get(id)
|
|
240
|
+
if (!s) continue
|
|
241
|
+
out.push({
|
|
242
|
+
kind: MY_WORK_GROUP_PINNED,
|
|
243
|
+
sessionId: s.id,
|
|
244
|
+
title: s.title,
|
|
245
|
+
status: s.status,
|
|
246
|
+
timeUpdated: s.timeUpdated,
|
|
247
|
+
})
|
|
248
|
+
}
|
|
249
|
+
return out
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** Parse the persisted dismissed-question set (a JSON array of part ids) from the kv store. */
|
|
253
|
+
export function parseDismissed(raw: string | null | undefined): ReadonlySet<string> {
|
|
254
|
+
if (!raw) return new Set()
|
|
255
|
+
try {
|
|
256
|
+
const value = JSON.parse(raw)
|
|
257
|
+
if (!Array.isArray(value)) return new Set()
|
|
258
|
+
return new Set(value.filter((x): x is string => typeof x === "string" && x.length > 0))
|
|
259
|
+
} catch {
|
|
260
|
+
return new Set()
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/** Serialize a dismissed-question id set back to the JSON string the kv store holds. */
|
|
265
|
+
export function formatDismissed(ids: ReadonlySet<string>): string {
|
|
266
|
+
return JSON.stringify([...ids])
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export function dropDismissed(
|
|
270
|
+
items: readonly MyWorkItem[],
|
|
271
|
+
dismissed: ReadonlySet<string>,
|
|
272
|
+
): MyWorkItem[] {
|
|
273
|
+
return items.map((i) => {
|
|
274
|
+
if (!("partId" in i)) return i
|
|
275
|
+
const byId = dismissed.has(i.partId)
|
|
276
|
+
const byReason = i.kind === QUESTION_KIND_ERROR
|
|
277
|
+
&& typeof i.reason === "string"
|
|
278
|
+
&& i.reason.toLowerCase().includes("dismissed this question")
|
|
279
|
+
if (!byId && !byReason) return i
|
|
280
|
+
return { ...i, kind: MY_WORK_GROUP_DISMISSED }
|
|
281
|
+
})
|
|
282
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { DocView } from "../pware.oc.omo/resolver/pware.oc.omo.resolver.doc.js"
|
|
2
|
+
import {
|
|
3
|
+
DraftFile,
|
|
4
|
+
sessionForPlanFile,
|
|
5
|
+
} from "../pware.oc.omo/resolver/index.js"
|
|
6
|
+
import { readonlyReadGateway } from "../pware.oc.core/pware.oc.core.sqliteGateway.js"
|
|
7
|
+
|
|
8
|
+
export type PlanSessionRead = {
|
|
9
|
+
readonly dbAvailable: boolean
|
|
10
|
+
readonly sessionId: string | null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function readSessionDrafts(opts: {
|
|
14
|
+
readonly dbPath: string
|
|
15
|
+
readonly projectRoot: string | null
|
|
16
|
+
readonly sessionId: string
|
|
17
|
+
}): Promise<DocView[]> {
|
|
18
|
+
if (!opts.projectRoot || !opts.sessionId) return Promise.resolve([])
|
|
19
|
+
return readonlyReadGateway.run<DocView[]>({
|
|
20
|
+
dbPath: opts.dbPath,
|
|
21
|
+
initial: () => [] as DocView[],
|
|
22
|
+
stages: [(db) => DraftFile.list(opts.projectRoot, opts.sessionId, { db })],
|
|
23
|
+
fallback: () => [],
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function readPlanSession(opts: {
|
|
28
|
+
readonly dbPath: string
|
|
29
|
+
readonly rel: string
|
|
30
|
+
}): Promise<PlanSessionRead> {
|
|
31
|
+
return readonlyReadGateway.run<PlanSessionRead>({
|
|
32
|
+
dbPath: opts.dbPath,
|
|
33
|
+
initial: () => ({ dbAvailable: true, sessionId: null }),
|
|
34
|
+
stages: [(db) => ({ dbAvailable: true, sessionId: sessionForPlanFile(db, opts.rel) })],
|
|
35
|
+
fallback: () => ({ dbAvailable: false, sessionId: null }),
|
|
36
|
+
})
|
|
37
|
+
}
|