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,43 +1,44 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* pware.oc.runtime.worker
|
|
3
|
-
*
|
|
4
|
-
* Runs `readRuntimeSnapshot` off the TUI main thread. A Bun Worker receiving
|
|
5
|
-
* `{type:"snapshot", id, opts}` replies `{type:"snapshot:done", id, ok, snap}`;
|
|
6
|
-
* `{type:"shutdown"}` closes the worker. The sync resolvers run unchanged in
|
|
7
|
-
* this thread, so the unit/snapshot test surface stays intact.
|
|
8
|
-
*/
|
|
9
|
-
import { readRuntimeSnapshot } from "./resolver/index.js"
|
|
10
|
-
|
|
11
|
-
type SnapshotRequest = {
|
|
12
|
-
type: "snapshot"
|
|
13
|
-
id: number
|
|
14
|
-
opts: { sessionId: string; projectRoot: string | null; dbPath?: string; questionHint?: string }
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
type ShutdownRequest = { type: "shutdown" }
|
|
18
|
-
|
|
19
|
-
type WorkerScope = {
|
|
20
|
-
onmessage: ((event: MessageEvent<SnapshotRequest | ShutdownRequest>) => void) | null
|
|
21
|
-
postMessage: (message: unknown) => void
|
|
22
|
-
close: () => void
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const scope = self as unknown as WorkerScope
|
|
26
|
-
|
|
27
|
-
scope.onmessage = (event) => {
|
|
28
|
-
const msg = event.data
|
|
29
|
-
if (msg.type === "shutdown") {
|
|
30
|
-
scope.close()
|
|
31
|
-
return
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* pware.oc.runtime.worker
|
|
3
|
+
*
|
|
4
|
+
* Runs `readRuntimeSnapshot` off the TUI main thread. A Bun Worker receiving
|
|
5
|
+
* `{type:"snapshot", id, opts}` replies `{type:"snapshot:done", id, ok, snap}`;
|
|
6
|
+
* `{type:"shutdown"}` closes the worker. The sync resolvers run unchanged in
|
|
7
|
+
* this thread, so the unit/snapshot test surface stays intact.
|
|
8
|
+
*/
|
|
9
|
+
import { readRuntimeSnapshot } from "./resolver/index.js"
|
|
10
|
+
|
|
11
|
+
type SnapshotRequest = {
|
|
12
|
+
type: "snapshot"
|
|
13
|
+
id: number
|
|
14
|
+
opts: { sessionId: string; projectRoot: string | null; dbPath?: string; questionHint?: string }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type ShutdownRequest = { type: "shutdown" }
|
|
18
|
+
|
|
19
|
+
type WorkerScope = {
|
|
20
|
+
onmessage: ((event: MessageEvent<SnapshotRequest | ShutdownRequest>) => void) | null
|
|
21
|
+
postMessage: (message: unknown) => void
|
|
22
|
+
close: () => void
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const scope = self as unknown as WorkerScope
|
|
26
|
+
|
|
27
|
+
scope.onmessage = async (event) => {
|
|
28
|
+
const msg = event.data
|
|
29
|
+
if (msg.type === "shutdown") {
|
|
30
|
+
scope.close()
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const snap = await readRuntimeSnapshot(msg.opts)
|
|
35
|
+
scope.postMessage({ type: "snapshot:done", id: msg.id, ok: true, snap })
|
|
36
|
+
} catch (err) {
|
|
37
|
+
scope.postMessage({
|
|
38
|
+
type: "snapshot:done",
|
|
39
|
+
id: msg.id,
|
|
40
|
+
ok: false,
|
|
41
|
+
error: err instanceof Error ? err.message : String(err),
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -1,224 +1,268 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* pware.oc.core.live.resolver
|
|
3
|
-
*
|
|
4
|
-
* Unified live snapshot: OpenCode SQLite + OMO files.
|
|
5
|
-
* Fingerprint-driven — callers poll / watch and call readRuntimeSnapshot.
|
|
6
|
-
*/
|
|
7
|
-
import { createStampCache } from "../../pware.oc.core/pware.oc.core.cache.js"
|
|
8
|
-
import { gitignoreStamp } from "../../pware.oc.core/git/pware.oc.core.gitignore.js"
|
|
9
|
-
import { oesStamp, getOes } from "../../pware.oc.core/pware.oc.core.oes.js"
|
|
10
|
-
import { dbStamp, getOpenCodeDbPath } from "../../pware.oc.core/pware.oc.core.paths.js"
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
emptyDb,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
type
|
|
20
|
-
type
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
export
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
generatedAt: now,
|
|
127
|
-
fingerprint:
|
|
128
|
-
scanStamp:
|
|
129
|
-
db:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
()
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const
|
|
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
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* pware.oc.core.live.resolver
|
|
3
|
+
*
|
|
4
|
+
* Unified live snapshot: OpenCode SQLite + OMO files.
|
|
5
|
+
* Fingerprint-driven — callers poll / watch and call readRuntimeSnapshot.
|
|
6
|
+
*/
|
|
7
|
+
import { createStampCache } from "../../pware.oc.core/pware.oc.core.cache.js"
|
|
8
|
+
import { gitignoreStamp } from "../../pware.oc.core/git/pware.oc.core.gitignore.js"
|
|
9
|
+
import { oesStamp, getOes } from "../../pware.oc.core/pware.oc.core.oes.js"
|
|
10
|
+
import { dbStamp, getOpenCodeDbPath } from "../../pware.oc.core/pware.oc.core.paths.js"
|
|
11
|
+
import { profileAsync } from "../../pware.oc.core/pware.oc.core.debug.js"
|
|
12
|
+
import {
|
|
13
|
+
createDbSnapshotRead,
|
|
14
|
+
emptyDb,
|
|
15
|
+
listOpenQuestions,
|
|
16
|
+
listSessionQuestions,
|
|
17
|
+
refreshSessionStatus,
|
|
18
|
+
sessionScanStamp,
|
|
19
|
+
type DbSnapshot,
|
|
20
|
+
type OpenQuestion,
|
|
21
|
+
type SessionView,
|
|
22
|
+
} from "../../pware.oc.opencode/resolver/index.js"
|
|
23
|
+
import { createQuestionCache } from "../pware.oc.runtime.questions.js"
|
|
24
|
+
import { readonlyReadGateway } from "../../pware.oc.core/pware.oc.core.sqliteGateway.js"
|
|
25
|
+
import {
|
|
26
|
+
emptyOmo,
|
|
27
|
+
omoStamp,
|
|
28
|
+
readOmo,
|
|
29
|
+
readOmoConfig,
|
|
30
|
+
type OmoConfigView,
|
|
31
|
+
type OmoSnapshot,
|
|
32
|
+
} from "../../pware.oc.omo/resolver/index.js"
|
|
33
|
+
import { enrichDelegates, type DelegateView } from "./pware.oc.runtime.resolver.delegate.js"
|
|
34
|
+
|
|
35
|
+
export * from "./pware.oc.runtime.resolver.delegate.js"
|
|
36
|
+
|
|
37
|
+
export type RuntimeSnapshot = {
|
|
38
|
+
generatedAt: number
|
|
39
|
+
fingerprint: string
|
|
40
|
+
/** session.time_updated + MAX(part.time_updated) — Perf cache key, not git. */
|
|
41
|
+
scanStamp: string
|
|
42
|
+
db: DbSnapshot
|
|
43
|
+
omo: OmoSnapshot
|
|
44
|
+
omoConfig: OmoConfigView
|
|
45
|
+
delegates: DelegateView[]
|
|
46
|
+
/** Open `question` tools across the project — computed off the UI thread. */
|
|
47
|
+
openQuestions: OpenQuestion[]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Cheap poll key: WAL + omo/oes stamps. No git, no boulder JSON. */
|
|
51
|
+
export function computeFingerprint(opts: {
|
|
52
|
+
dbPath: string
|
|
53
|
+
projectRoot: string | null
|
|
54
|
+
sessionId: string
|
|
55
|
+
}): string {
|
|
56
|
+
return [
|
|
57
|
+
opts.sessionId,
|
|
58
|
+
dbStamp(opts.dbPath),
|
|
59
|
+
omoStamp(opts.projectRoot),
|
|
60
|
+
oesStamp(opts.projectRoot),
|
|
61
|
+
gitignoreStamp(opts.projectRoot),
|
|
62
|
+
].join("::")
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
type RuntimeDbRead = {
|
|
66
|
+
readonly ok: boolean
|
|
67
|
+
readonly db: DbSnapshot
|
|
68
|
+
readonly scanStamp: string
|
|
69
|
+
readonly questions: readonly OpenQuestion[] | null
|
|
70
|
+
readonly questionSessionId: string | null
|
|
71
|
+
readonly fullQuestionScan: boolean
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export async function readRuntimeSnapshot(opts: {
|
|
75
|
+
sessionId: string
|
|
76
|
+
projectRoot: string | null
|
|
77
|
+
dbPath?: string
|
|
78
|
+
questionHint?: string
|
|
79
|
+
}): Promise<RuntimeSnapshot> {
|
|
80
|
+
const dbPath = opts.dbPath || getOpenCodeDbPath(process.env, undefined, opts.projectRoot)
|
|
81
|
+
const cheap = computeFingerprint({
|
|
82
|
+
dbPath,
|
|
83
|
+
projectRoot: opts.projectRoot,
|
|
84
|
+
sessionId: opts.sessionId,
|
|
85
|
+
})
|
|
86
|
+
const hit = liveCache.peek(cheap)
|
|
87
|
+
if (hit) {
|
|
88
|
+
const now = Date.now()
|
|
89
|
+
const questionHint = opts.questionHint
|
|
90
|
+
const projectId = hit.db.projectId
|
|
91
|
+
if (questionHint && projectId) {
|
|
92
|
+
const questionRead = await profileAsync("db.questions", () =>
|
|
93
|
+
readonlyReadGateway.run<{ readonly ok: boolean; readonly questions: OpenQuestion[] }>({
|
|
94
|
+
dbPath,
|
|
95
|
+
initial: () => ({ ok: true, questions: [] }),
|
|
96
|
+
stages: [(db) => ({
|
|
97
|
+
ok: true,
|
|
98
|
+
questions: listSessionQuestions(db, questionHint, projectId),
|
|
99
|
+
})],
|
|
100
|
+
fallback: () => ({ ok: false, questions: [] }),
|
|
101
|
+
}),
|
|
102
|
+
)
|
|
103
|
+
if (questionRead.ok) questionCache.touch(questionHint, questionRead.questions)
|
|
104
|
+
return {
|
|
105
|
+
...hit,
|
|
106
|
+
generatedAt: now,
|
|
107
|
+
fingerprint: cheap,
|
|
108
|
+
db: withAges(hit.db, now),
|
|
109
|
+
openQuestions: questionCache.get(),
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
...hit,
|
|
114
|
+
generatedAt: now,
|
|
115
|
+
fingerprint: cheap,
|
|
116
|
+
db: withAges(hit.db, now),
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const omo = readOmo(opts.projectRoot)
|
|
121
|
+
const extraIds = omo.delegates
|
|
122
|
+
.map((d) => d.sessionId)
|
|
123
|
+
.filter((id): id is string => Boolean(id))
|
|
124
|
+
if (!opts.sessionId) {
|
|
125
|
+
return {
|
|
126
|
+
generatedAt: Date.now(),
|
|
127
|
+
fingerprint: cheap,
|
|
128
|
+
scanStamp: "0",
|
|
129
|
+
db: emptyDb(dbPath, "no session"),
|
|
130
|
+
omo,
|
|
131
|
+
omoConfig: readOmoConfig(),
|
|
132
|
+
delegates: [],
|
|
133
|
+
openQuestions: [],
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const plan = createDbSnapshotRead({
|
|
138
|
+
dbPath,
|
|
139
|
+
sessionId: opts.sessionId,
|
|
140
|
+
extraIds,
|
|
141
|
+
projectRoot: opts.projectRoot,
|
|
142
|
+
})
|
|
143
|
+
const reconcileQuestions =
|
|
144
|
+
Date.now() - questionLastReconcile >= getOes(opts.projectRoot).questionReconcileSec * 1000
|
|
145
|
+
const initial = (): RuntimeDbRead => ({
|
|
146
|
+
ok: true,
|
|
147
|
+
db: plan.initial(),
|
|
148
|
+
scanStamp: "0",
|
|
149
|
+
questions: null,
|
|
150
|
+
questionSessionId: opts.questionHint ?? null,
|
|
151
|
+
fullQuestionScan: false,
|
|
152
|
+
})
|
|
153
|
+
const snapshotStages = plan.stages.map((stage) =>
|
|
154
|
+
(db: Parameters<typeof stage>[0], state: RuntimeDbRead): RuntimeDbRead => ({
|
|
155
|
+
...state,
|
|
156
|
+
db: stage(db, state.db),
|
|
157
|
+
}))
|
|
158
|
+
const read = await profileAsync("db.snapshot", () =>
|
|
159
|
+
readonlyReadGateway.run({
|
|
160
|
+
dbPath,
|
|
161
|
+
initial,
|
|
162
|
+
stages: [
|
|
163
|
+
...snapshotStages,
|
|
164
|
+
(db, state) => ({ ...state, scanStamp: sessionScanStamp(db, opts.sessionId) }),
|
|
165
|
+
(db, state) => {
|
|
166
|
+
const projectId = state.db.projectId
|
|
167
|
+
if (!projectId) return state
|
|
168
|
+
if (opts.questionHint) {
|
|
169
|
+
return {
|
|
170
|
+
...state,
|
|
171
|
+
questions: listSessionQuestions(db, opts.questionHint, projectId),
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (projectId === questionProjectId && !reconcileQuestions) return state
|
|
175
|
+
return {
|
|
176
|
+
...state,
|
|
177
|
+
questions: listOpenQuestions(db, projectId),
|
|
178
|
+
fullQuestionScan: true,
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
fallback: () => ({
|
|
183
|
+
ok: false,
|
|
184
|
+
db:
|
|
185
|
+
lastGood?.db.current?.id === opts.sessionId
|
|
186
|
+
? lastGood.db
|
|
187
|
+
: emptyDb(dbPath, "db read failed"),
|
|
188
|
+
scanStamp: lastGood?.scanStamp ?? "0",
|
|
189
|
+
questions: null,
|
|
190
|
+
questionSessionId: null,
|
|
191
|
+
fullQuestionScan: false,
|
|
192
|
+
}),
|
|
193
|
+
}),
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
if (!read.ok && lastGood?.db.current?.id === opts.sessionId) {
|
|
197
|
+
return { ...lastGood, generatedAt: Date.now(), db: withAges(lastGood.db, Date.now()) }
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const projectId = read.db.projectId
|
|
201
|
+
if (projectId && projectId !== questionProjectId) {
|
|
202
|
+
questionCache.reset()
|
|
203
|
+
questionProjectId = projectId
|
|
204
|
+
questionLastReconcile = 0
|
|
205
|
+
}
|
|
206
|
+
if (read.questions) {
|
|
207
|
+
if (read.questionSessionId) questionCache.touch(read.questionSessionId, read.questions)
|
|
208
|
+
else if (read.fullQuestionScan) {
|
|
209
|
+
questionCache.seed(read.questions)
|
|
210
|
+
questionLastReconcile = Date.now()
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
const openQuestions = projectId ? questionCache.get() : []
|
|
214
|
+
|
|
215
|
+
const snap: RuntimeSnapshot = {
|
|
216
|
+
generatedAt: Date.now(),
|
|
217
|
+
fingerprint: cheap,
|
|
218
|
+
scanStamp: read.scanStamp,
|
|
219
|
+
db: read.db,
|
|
220
|
+
omo,
|
|
221
|
+
omoConfig: readOmoConfig(),
|
|
222
|
+
delegates: enrichDelegates(omo, read.db),
|
|
223
|
+
openQuestions,
|
|
224
|
+
}
|
|
225
|
+
lastGood = snap
|
|
226
|
+
liveCache.set(cheap, snap)
|
|
227
|
+
return snap
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const liveCache = createStampCache<RuntimeSnapshot>()
|
|
231
|
+
|
|
232
|
+
/** Last successfully-read snapshot, served when a locked DB read fails. */
|
|
233
|
+
let lastGood: RuntimeSnapshot | null = null
|
|
234
|
+
|
|
235
|
+
/** Module-level open-question cache — seeded once, invalidated per-session via questionHint. */
|
|
236
|
+
const questionCache = createQuestionCache()
|
|
237
|
+
let questionLastReconcile = 0
|
|
238
|
+
let questionProjectId: string | null = null
|
|
239
|
+
|
|
240
|
+
/** Drop the in-memory live snapshot so the next read is a real load. */
|
|
241
|
+
export function resetRuntimeCache(): void {
|
|
242
|
+
liveCache.reset()
|
|
243
|
+
lastGood = null
|
|
244
|
+
questionCache.reset()
|
|
245
|
+
questionLastReconcile = 0
|
|
246
|
+
questionProjectId = null
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function withAges(db: DbSnapshot, now: number): DbSnapshot {
|
|
250
|
+
const bump = (v: SessionView | null): SessionView | null =>
|
|
251
|
+
v
|
|
252
|
+
? {
|
|
253
|
+
...v,
|
|
254
|
+
ageMs: Math.max(0, now - v.timeUpdated),
|
|
255
|
+
status: refreshSessionStatus(v, now),
|
|
256
|
+
}
|
|
257
|
+
: null
|
|
258
|
+
const current = bump(db.current)
|
|
259
|
+
const parent = bump(db.parent)
|
|
260
|
+
const main = bump(db.main)
|
|
261
|
+
const children = db.children.map((v) => bump(v)!)
|
|
262
|
+
const recent = db.recent.map((v) => bump(v)!)
|
|
263
|
+
const byId: DbSnapshot["byId"] = {}
|
|
264
|
+
for (const v of [current, parent, main, ...children, ...recent, ...Object.values(db.byId).map((x) => bump(x)!)]) {
|
|
265
|
+
if (v) byId[v.id] = v
|
|
266
|
+
}
|
|
267
|
+
return { ...db, current, parent, main, children, recent, byId }
|
|
268
|
+
}
|