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,211 +1,248 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* pware.oc.core.opencode.resolver.session
|
|
3
|
-
*
|
|
4
|
-
* Session rows → SessionView plus the hierarchy queries (current, children,
|
|
5
|
-
* siblings, recent mains, lookups by id). Read-only against opencode.db.
|
|
6
|
-
*/
|
|
7
|
-
import { uniqueIds, type SqlDb } from "../../pware.oc.core/pware.oc.core.sqlite.js"
|
|
8
|
-
import {
|
|
9
|
-
SESSION_STATE_ARCHIVED,
|
|
10
|
-
SESSION_STATE_AWAITING_BACKGROUND,
|
|
11
|
-
SESSION_STATE_IDLE,
|
|
12
|
-
SESSION_STATE_STREAMING,
|
|
13
|
-
SESSION_STATE_UNKNOWN,
|
|
14
|
-
SESSION_STATUS_ARCHIVED,
|
|
15
|
-
SESSION_STATUS_IDLE,
|
|
16
|
-
SESSION_STATUS_RUNNING,
|
|
17
|
-
SESSION_STATUS_UNKNOWN,
|
|
18
|
-
type AgentStatus,
|
|
19
|
-
type SessionState,
|
|
20
|
-
} from "../constants/pware.oc.opencode.constants.sessionStatus.js"
|
|
21
|
-
|
|
22
|
-
export type { AgentStatus, SessionState }
|
|
23
|
-
|
|
24
|
-
export type SessionRow = {
|
|
25
|
-
id: string
|
|
26
|
-
project_id: string
|
|
27
|
-
parent_id: string | null
|
|
28
|
-
directory: string
|
|
29
|
-
title: string
|
|
30
|
-
agent: string | null
|
|
31
|
-
model: string | null
|
|
32
|
-
cost: number
|
|
33
|
-
tokens_input: number
|
|
34
|
-
tokens_output: number
|
|
35
|
-
tokens_reasoning: number
|
|
36
|
-
time_created: number
|
|
37
|
-
time_updated: number
|
|
38
|
-
time_archived: number | null
|
|
39
|
-
/** 1 when the session has at least one part, 0 for an empty shell (ghost). */
|
|
40
|
-
has_content: number
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** Finer-grained "is this session still working" state for approval rows. */
|
|
44
|
-
export type SessionActivityState = {
|
|
45
|
-
running: boolean
|
|
46
|
-
state: SessionState
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export type SessionView = {
|
|
50
|
-
id: string
|
|
51
|
-
title: string
|
|
52
|
-
agent: string
|
|
53
|
-
status: AgentStatus
|
|
54
|
-
isMain: boolean
|
|
55
|
-
parentId: string | null
|
|
56
|
-
directory: string
|
|
57
|
-
tokensTotal: number
|
|
58
|
-
cost: number
|
|
59
|
-
timeUpdated: number
|
|
60
|
-
ageMs: number
|
|
61
|
-
hasContent: boolean
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const RUNNING_MS = 2 * 60 * 1000
|
|
65
|
-
|
|
66
|
-
const
|
|
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
|
-
if (
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
return
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return
|
|
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
|
-
|
|
1
|
+
/**
|
|
2
|
+
* pware.oc.core.opencode.resolver.session
|
|
3
|
+
*
|
|
4
|
+
* Session rows → SessionView plus the hierarchy queries (current, children,
|
|
5
|
+
* siblings, recent mains, lookups by id). Read-only against opencode.db.
|
|
6
|
+
*/
|
|
7
|
+
import { uniqueIds, type SqlDb } from "../../pware.oc.core/pware.oc.core.sqlite.js"
|
|
8
|
+
import {
|
|
9
|
+
SESSION_STATE_ARCHIVED,
|
|
10
|
+
SESSION_STATE_AWAITING_BACKGROUND,
|
|
11
|
+
SESSION_STATE_IDLE,
|
|
12
|
+
SESSION_STATE_STREAMING,
|
|
13
|
+
SESSION_STATE_UNKNOWN,
|
|
14
|
+
SESSION_STATUS_ARCHIVED,
|
|
15
|
+
SESSION_STATUS_IDLE,
|
|
16
|
+
SESSION_STATUS_RUNNING,
|
|
17
|
+
SESSION_STATUS_UNKNOWN,
|
|
18
|
+
type AgentStatus,
|
|
19
|
+
type SessionState,
|
|
20
|
+
} from "../constants/pware.oc.opencode.constants.sessionStatus.js"
|
|
21
|
+
|
|
22
|
+
export type { AgentStatus, SessionState }
|
|
23
|
+
|
|
24
|
+
export type SessionRow = {
|
|
25
|
+
id: string
|
|
26
|
+
project_id: string
|
|
27
|
+
parent_id: string | null
|
|
28
|
+
directory: string
|
|
29
|
+
title: string
|
|
30
|
+
agent: string | null
|
|
31
|
+
model: string | null
|
|
32
|
+
cost: number
|
|
33
|
+
tokens_input: number
|
|
34
|
+
tokens_output: number
|
|
35
|
+
tokens_reasoning: number
|
|
36
|
+
time_created: number
|
|
37
|
+
time_updated: number
|
|
38
|
+
time_archived: number | null
|
|
39
|
+
/** 1 when the session has at least one part, 0 for an empty shell (ghost). */
|
|
40
|
+
has_content: number
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Finer-grained "is this session still working" state for approval rows. */
|
|
44
|
+
export type SessionActivityState = {
|
|
45
|
+
running: boolean
|
|
46
|
+
state: SessionState
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export type SessionView = {
|
|
50
|
+
id: string
|
|
51
|
+
title: string
|
|
52
|
+
agent: string
|
|
53
|
+
status: AgentStatus
|
|
54
|
+
isMain: boolean
|
|
55
|
+
parentId: string | null
|
|
56
|
+
directory: string
|
|
57
|
+
tokensTotal: number
|
|
58
|
+
cost: number
|
|
59
|
+
timeUpdated: number
|
|
60
|
+
ageMs: number
|
|
61
|
+
hasContent: boolean
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const RUNNING_MS = 2 * 60 * 1000
|
|
65
|
+
|
|
66
|
+
export const HOUR_MS = 3_600_000
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Age tier for a session row: how bright should it render?
|
|
70
|
+
*
|
|
71
|
+
* - `keep` (pinned/current) is always full.
|
|
72
|
+
* - `ageMs` null or NaN (unknown / uncomputed) is treated as full — defensive,
|
|
73
|
+
* never hide a row whose age we do not know.
|
|
74
|
+
* - age < dimMs → full
|
|
75
|
+
* - age < visibleMs → dim
|
|
76
|
+
* - otherwise → hidden
|
|
77
|
+
*
|
|
78
|
+
* Boundaries: age exactly `dimMs` is `dim`; age exactly `visibleMs` is `hidden`.
|
|
79
|
+
*/
|
|
80
|
+
export function sessionAgeTier(
|
|
81
|
+
ageMs: number | null,
|
|
82
|
+
dimMs: number,
|
|
83
|
+
visibleMs: number,
|
|
84
|
+
keep: boolean,
|
|
85
|
+
): "full" | "dim" | "hidden" {
|
|
86
|
+
if (keep) return "full"
|
|
87
|
+
if (ageMs == null || Number.isNaN(ageMs)) return "full"
|
|
88
|
+
if (ageMs < dimMs) return "full"
|
|
89
|
+
if (ageMs < visibleMs) return "dim"
|
|
90
|
+
return "hidden"
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Row opacity is the single decision point: dim rows render at 0.5, everything
|
|
95
|
+
* else (full, hidden, kept) uses the renderer default. Never hardcode 0.5
|
|
96
|
+
* elsewhere — callers import this.
|
|
97
|
+
*/
|
|
98
|
+
export function sessionRowOpacity(
|
|
99
|
+
ageMs: number | null,
|
|
100
|
+
dimMs: number,
|
|
101
|
+
visibleMs: number,
|
|
102
|
+
keep: boolean,
|
|
103
|
+
): number | undefined {
|
|
104
|
+
return sessionAgeTier(ageMs, dimMs, visibleMs, keep) === "dim" ? 0.5 : undefined
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const SESSION_SELECT = `
|
|
108
|
+
id, project_id, parent_id, directory, title, agent, model,
|
|
109
|
+
cost, tokens_input, tokens_output, tokens_reasoning,
|
|
110
|
+
time_created, time_updated, time_archived,
|
|
111
|
+
EXISTS (SELECT 1 FROM part WHERE part.session_id = session.id) AS has_content
|
|
112
|
+
`
|
|
113
|
+
|
|
114
|
+
export function inferStatus(row: SessionRow, now = Date.now()): AgentStatus {
|
|
115
|
+
if (row.time_archived) return SESSION_STATUS_ARCHIVED
|
|
116
|
+
const age = now - (row.time_updated || 0)
|
|
117
|
+
if (age < 0) return SESSION_STATUS_UNKNOWN
|
|
118
|
+
if (age <= RUNNING_MS) return SESSION_STATUS_RUNNING
|
|
119
|
+
return SESSION_STATUS_IDLE
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function toSessionView(row: SessionRow, now = Date.now()): SessionView {
|
|
123
|
+
const ti = row.tokens_input || 0
|
|
124
|
+
const to = row.tokens_output || 0
|
|
125
|
+
const tr = row.tokens_reasoning || 0
|
|
126
|
+
return {
|
|
127
|
+
id: row.id,
|
|
128
|
+
title: row.title?.trim() || "untitled",
|
|
129
|
+
agent: row.agent?.trim() || "unknown",
|
|
130
|
+
status: inferStatus(row, now),
|
|
131
|
+
isMain: !row.parent_id,
|
|
132
|
+
parentId: row.parent_id,
|
|
133
|
+
directory: row.directory,
|
|
134
|
+
tokensTotal: ti + to + tr,
|
|
135
|
+
cost: row.cost || 0,
|
|
136
|
+
timeUpdated: row.time_updated,
|
|
137
|
+
ageMs: Math.max(0, now - (row.time_updated || 0)),
|
|
138
|
+
hasContent: row.has_content === 1,
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** A session with real content (≥1 part). A ghost — created but never prompted — is false. */
|
|
143
|
+
export function isRealSession(view: Pick<SessionView, "hasContent"> | null | undefined): boolean {
|
|
144
|
+
return Boolean(view?.hasContent)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Recompute a `SessionView` status against a fresh clock. The live snapshot
|
|
149
|
+
* cache refreshes `ageMs` on every hit, so `status` (also age-derived) must be
|
|
150
|
+
* refreshed with it — otherwise a session that went idle keeps reading running.
|
|
151
|
+
*/
|
|
152
|
+
export function refreshSessionStatus(view: SessionView, now: number): AgentStatus {
|
|
153
|
+
if (view.status === SESSION_STATUS_ARCHIVED) return SESSION_STATUS_ARCHIVED
|
|
154
|
+
const age = now - view.timeUpdated
|
|
155
|
+
if (age < 0) return SESSION_STATUS_UNKNOWN
|
|
156
|
+
if (age <= RUNNING_MS) return SESSION_STATUS_RUNNING
|
|
157
|
+
return SESSION_STATUS_IDLE
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function getSessionById(db: SqlDb, id: string): SessionRow | null {
|
|
161
|
+
return db.get<SessionRow>(
|
|
162
|
+
`SELECT ${SESSION_SELECT} FROM session WHERE id = ? LIMIT 1`,
|
|
163
|
+
id,
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Is this session still working, and how? Streaming = a fresh `time_updated`;
|
|
169
|
+
* awaiting-background = stale in SQLite but the caller's already-resolved
|
|
170
|
+
* `backgroundTaskActive` (`.omo/run-continuation` marker) is true;
|
|
171
|
+
* idle/archived/unknown otherwise. The omo layer resolves the marker — this
|
|
172
|
+
* opencode function never reads omo files.
|
|
173
|
+
*/
|
|
174
|
+
export function sessionActivityState(
|
|
175
|
+
db: SqlDb,
|
|
176
|
+
sessionId: string,
|
|
177
|
+
opts?: { backgroundTaskActive?: boolean | null; now?: number },
|
|
178
|
+
): SessionActivityState {
|
|
179
|
+
const row = getSessionById(db, sessionId)
|
|
180
|
+
if (!row) return { running: false, state: SESSION_STATE_UNKNOWN }
|
|
181
|
+
if (row.time_archived) return { running: false, state: SESSION_STATE_ARCHIVED }
|
|
182
|
+
const now = opts?.now ?? Date.now()
|
|
183
|
+
if (now - row.time_updated <= RUNNING_MS) return { running: true, state: SESSION_STATE_STREAMING }
|
|
184
|
+
if (opts?.backgroundTaskActive) return { running: true, state: SESSION_STATE_AWAITING_BACKGROUND }
|
|
185
|
+
return { running: false, state: SESSION_STATE_IDLE }
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function listChildSessions(db: SqlDb, parentId: string): SessionRow[] {
|
|
189
|
+
return db.all<SessionRow>(
|
|
190
|
+
`SELECT ${SESSION_SELECT} FROM session WHERE parent_id = ? ORDER BY time_updated DESC LIMIT 40`,
|
|
191
|
+
parentId,
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export function listSiblingSessions(db: SqlDb, parentId: string, excludeId: string): SessionRow[] {
|
|
196
|
+
return db.all<SessionRow>(
|
|
197
|
+
`SELECT ${SESSION_SELECT} FROM session
|
|
198
|
+
WHERE parent_id = ? AND id != ?
|
|
199
|
+
ORDER BY time_updated DESC LIMIT 40`,
|
|
200
|
+
parentId,
|
|
201
|
+
excludeId,
|
|
202
|
+
)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const RECENT_LIMIT = 4
|
|
206
|
+
|
|
207
|
+
export function listRecentMainSessions(
|
|
208
|
+
db: SqlDb,
|
|
209
|
+
opts: { projectId: string; limit?: number },
|
|
210
|
+
): SessionRow[] {
|
|
211
|
+
const limit = Math.max(1, Math.min(opts.limit ?? RECENT_LIMIT, 20))
|
|
212
|
+
return db.all<SessionRow>(
|
|
213
|
+
`SELECT ${SESSION_SELECT} FROM session
|
|
214
|
+
WHERE parent_id IS NULL
|
|
215
|
+
AND (time_archived IS NULL OR time_archived = 0)
|
|
216
|
+
AND project_id = ?
|
|
217
|
+
AND EXISTS (SELECT 1 FROM part WHERE part.session_id = session.id)
|
|
218
|
+
ORDER BY time_updated DESC
|
|
219
|
+
LIMIT ${limit}`,
|
|
220
|
+
opts.projectId,
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export function getSessionsByIds(db: SqlDb, ids: string[]): SessionRow[] {
|
|
225
|
+
const clean = uniqueIds(ids)
|
|
226
|
+
if (clean.length === 0) return []
|
|
227
|
+
const placeholders = clean.map(() => "?").join(",")
|
|
228
|
+
return db.all<SessionRow>(
|
|
229
|
+
`SELECT ${SESSION_SELECT} FROM session WHERE id IN (${placeholders})`,
|
|
230
|
+
...clean,
|
|
231
|
+
)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export function sessionScanStamp(db: SqlDb, sessionId: string): string {
|
|
235
|
+
try {
|
|
236
|
+
const s = db.get<{ time_updated: number }>(
|
|
237
|
+
`SELECT time_updated FROM session WHERE id = ? LIMIT 1`,
|
|
238
|
+
sessionId,
|
|
239
|
+
)
|
|
240
|
+
const p = db.get<{ m: number | null }>(
|
|
241
|
+
`SELECT MAX(time_updated) AS m FROM part WHERE session_id = ?`,
|
|
242
|
+
sessionId,
|
|
243
|
+
)
|
|
244
|
+
return `${s?.time_updated ?? 0}|${p?.m ?? 0}`
|
|
245
|
+
} catch {
|
|
246
|
+
return "x"
|
|
247
|
+
}
|
|
248
|
+
}
|
|
@@ -1,26 +1,22 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* pware.oc.core.opencode.resolver.todo
|
|
3
|
-
*
|
|
4
|
-
* Todo rows for one session — content, status, priority, position.
|
|
5
|
-
*/
|
|
6
|
-
import type { SqlDb } from "../../pware.oc.core/pware.oc.core.sqlite.js"
|
|
7
|
-
|
|
8
|
-
export type TodoRow = {
|
|
9
|
-
content: string
|
|
10
|
-
status: string
|
|
11
|
-
priority: string
|
|
12
|
-
position: number
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function listTodos(db: SqlDb, sessionId: string): TodoRow[] {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
} catch {
|
|
24
|
-
return []
|
|
25
|
-
}
|
|
26
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* pware.oc.core.opencode.resolver.todo
|
|
3
|
+
*
|
|
4
|
+
* Todo rows for one session — content, status, priority, position.
|
|
5
|
+
*/
|
|
6
|
+
import type { SqlDb } from "../../pware.oc.core/pware.oc.core.sqlite.js"
|
|
7
|
+
|
|
8
|
+
export type TodoRow = {
|
|
9
|
+
content: string
|
|
10
|
+
status: string
|
|
11
|
+
priority: string
|
|
12
|
+
position: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function listTodos(db: SqlDb, sessionId: string): TodoRow[] {
|
|
16
|
+
return db.all<TodoRow>(
|
|
17
|
+
`SELECT content, status, priority, position
|
|
18
|
+
FROM todo WHERE session_id = ?
|
|
19
|
+
ORDER BY position ASC LIMIT 40`,
|
|
20
|
+
sessionId,
|
|
21
|
+
)
|
|
22
|
+
}
|