@ash-qw/dsh-theme-prts 1.0.0 → 1.0.2
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/CHANGELOG.md +10 -0
- package/lib/client.js +73 -14
- package/package.json +1 -1
- package/src/client/index.js +2 -0
- package/src/client/sidebar-control-adapter.js +70 -12
- package/src/styles/facility-vector.css +30 -0
- package/src/styles/prts.css +12 -1
- package/src/styles/refinement.css +1 -1
package/package.json
CHANGED
package/src/client/index.js
CHANGED
|
@@ -91,6 +91,8 @@ export function applyPrtsPlugin(ctx, environment) {
|
|
|
91
91
|
window,
|
|
92
92
|
sessions: contextService(ctx, 'sessions'),
|
|
93
93
|
workspaces: contextService(ctx, 'workspaces'),
|
|
94
|
+
getSessionStatus: () => contextService(ctx, 'uiSession')?.sessionStatus,
|
|
95
|
+
getUiWorkspace: () => contextService(ctx, 'uiWorkspace'),
|
|
94
96
|
})
|
|
95
97
|
const floatingGlass = createFloatingGlassAdapter({ document, window })
|
|
96
98
|
const adapter = createRc7Adapter({ document })
|
|
@@ -30,6 +30,11 @@ const OWNED_ATTRIBUTES = [
|
|
|
30
30
|
]
|
|
31
31
|
|
|
32
32
|
const SESSION_STATES = Object.freeze(['warning', 'ongoing', 'error', 'done'])
|
|
33
|
+
const PENDING_LABELS = Object.freeze({
|
|
34
|
+
approval: '待授权',
|
|
35
|
+
'plan-review': '待审阅',
|
|
36
|
+
question: '待回答',
|
|
37
|
+
})
|
|
33
38
|
|
|
34
39
|
function snapshotOf(source) {
|
|
35
40
|
try {
|
|
@@ -62,17 +67,27 @@ function resolveSectionHeader(root) {
|
|
|
62
67
|
return {}
|
|
63
68
|
}
|
|
64
69
|
|
|
65
|
-
function visibleSessionSummaries(sessions, workspaces) {
|
|
70
|
+
function visibleSessionSummaries(sessions, workspaces, sessionStatus) {
|
|
66
71
|
const list = snapshotOf(sessions?.list)
|
|
67
72
|
if (!list?.byId) return []
|
|
73
|
+
const statuses = snapshotOf(sessionStatus)
|
|
68
74
|
const workspaceList = snapshotOf(workspaces?.list)
|
|
69
75
|
const archived = new Set(workspaceList?.archivedSessionIds ?? [])
|
|
70
76
|
const ids = Array.isArray(list.ids) ? list.ids : Object.keys(list.byId)
|
|
71
77
|
return ids.flatMap(id => {
|
|
72
78
|
const summary = list.byId[id]
|
|
73
79
|
if (!summary || summary.blank || summary.origin === 'subagent' || archived.has(id)) return []
|
|
74
|
-
|
|
75
|
-
|
|
80
|
+
const status = statuses?.get?.(id)
|
|
81
|
+
const pendingLabel = PENDING_LABELS[status?.pendingInteraction?.kind]
|
|
82
|
+
if (pendingLabel) return [{ id, title: summary.displayTitle || id, state: 'warning', statusLabel: pendingLabel }]
|
|
83
|
+
const runningSubagent = list.projectionsBySession?.[id]?.values?.subagentCatalog?.some(child =>
|
|
84
|
+
(statuses?.get?.(child.id)?.running ?? list.byId[child.id]?.running) === true)
|
|
85
|
+
if ((status?.running ?? summary.running) || runningSubagent) {
|
|
86
|
+
return [{ id, title: summary.displayTitle || id, state: 'ongoing' }]
|
|
87
|
+
}
|
|
88
|
+
if (status ? status.completionUnread === true : summary.completed === true) {
|
|
89
|
+
return [{ id, title: summary.displayTitle || id, state: 'done' }]
|
|
90
|
+
}
|
|
76
91
|
return []
|
|
77
92
|
})
|
|
78
93
|
}
|
|
@@ -139,11 +154,11 @@ function resolveSessionTime(row, title, actions) {
|
|
|
139
154
|
&& node !== actions
|
|
140
155
|
&& !node.hasAttribute('data-prts-facility-face')
|
|
141
156
|
&& !node.hasAttribute('data-prts-row-projection')
|
|
142
|
-
&& node.getAttribute('aria-hidden') !== 'true'
|
|
143
157
|
&& !node.querySelector('button')
|
|
144
158
|
&& node.textContent.trim()
|
|
145
159
|
))
|
|
146
|
-
return candidates.find(node => node.matches('[class*="time" i], time, [data-session-time]'))
|
|
160
|
+
return candidates.find(node => node.matches('[class*="time" i], time, [data-session-time]'))
|
|
161
|
+
?? candidates.filter(node => node.getAttribute('aria-hidden') !== 'true' && !node.querySelector('[data-state]')).at(-1)
|
|
147
162
|
}
|
|
148
163
|
|
|
149
164
|
function ensureFacilityFace(document, row, kind, next) {
|
|
@@ -174,7 +189,7 @@ function ensureFacilitySpine(document, row, kind, next) {
|
|
|
174
189
|
}
|
|
175
190
|
|
|
176
191
|
|
|
177
|
-
export function createSidebarControlAdapter({ document, window, sessions, workspaces }) {
|
|
192
|
+
export function createSidebarControlAdapter({ document, window, sessions, workspaces, getSessionStatus, getUiWorkspace }) {
|
|
178
193
|
let observer
|
|
179
194
|
let resizeObserver
|
|
180
195
|
let resizeFrame
|
|
@@ -182,6 +197,8 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
182
197
|
let scanFrame
|
|
183
198
|
let stopSessionList = () => {}
|
|
184
199
|
let stopWorkspaceList = () => {}
|
|
200
|
+
let stopSessionStatus = () => {}
|
|
201
|
+
let sessionStatus
|
|
185
202
|
let statusSourcesStarted = false
|
|
186
203
|
let summaryRoot
|
|
187
204
|
let summarySignature = ''
|
|
@@ -191,15 +208,30 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
191
208
|
const vectorSizes = new WeakMap()
|
|
192
209
|
const lifelineAnimator = createSessionLifelineAnimator({ document, window })
|
|
193
210
|
|
|
211
|
+
function connectSessionStatus() {
|
|
212
|
+
const source = getSessionStatus?.()
|
|
213
|
+
if (source === sessionStatus) return
|
|
214
|
+
stopSessionStatus()
|
|
215
|
+
sessionStatus = source
|
|
216
|
+
stopSessionStatus = source?.subscribe?.(queueScan) ?? (() => {})
|
|
217
|
+
}
|
|
218
|
+
|
|
194
219
|
function openSession(sessionId) {
|
|
195
220
|
try {
|
|
221
|
+
const uiWorkspace = getUiWorkspace?.()
|
|
222
|
+
if (typeof uiWorkspace?.openSession === 'function') {
|
|
223
|
+
uiWorkspace.openSession(sessionId)
|
|
224
|
+
return
|
|
225
|
+
}
|
|
196
226
|
if (typeof sessions?.open === 'function') {
|
|
197
227
|
sessions.open(sessionId)
|
|
198
228
|
return
|
|
199
229
|
}
|
|
200
230
|
} catch {}
|
|
201
231
|
const row = Array.from(document.querySelectorAll('[data-prts-session-row]')).find(candidate => (
|
|
202
|
-
candidate.
|
|
232
|
+
candidate.getAttribute('data-row-key') === `session:${sessionId}`
|
|
233
|
+
|| candidate.getAttribute('data-session-id') === sessionId
|
|
234
|
+
|| candidate.querySelector('[data-prts-row-title]')?.textContent.trim() === sessionId
|
|
203
235
|
))
|
|
204
236
|
row?.click?.()
|
|
205
237
|
}
|
|
@@ -247,6 +279,13 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
247
279
|
const title = document.createElement('span')
|
|
248
280
|
title.textContent = item.title
|
|
249
281
|
button.append(title)
|
|
282
|
+
if (item.statusLabel) {
|
|
283
|
+
const detail = document.createElement('small')
|
|
284
|
+
detail.setAttribute('data-prts-session-summary-item-status', '')
|
|
285
|
+
detail.textContent = item.statusLabel
|
|
286
|
+
button.append(detail)
|
|
287
|
+
button.setAttribute('aria-label', `${item.title},${item.statusLabel}`)
|
|
288
|
+
}
|
|
250
289
|
button.addEventListener('click', event => {
|
|
251
290
|
event.stopPropagation()
|
|
252
291
|
openSession(item.id)
|
|
@@ -269,16 +308,30 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
269
308
|
label.setAttribute('data-prts-session-summary-label', '')
|
|
270
309
|
next.add(header)
|
|
271
310
|
next.add(label)
|
|
272
|
-
const fromService = visibleSessionSummaries(sessions, workspaces)
|
|
273
|
-
const
|
|
311
|
+
const fromService = visibleSessionSummaries(sessions, workspaces, sessionStatus)
|
|
312
|
+
const nativeRows = Array.from(root.querySelectorAll('[data-prts-session-row]')).flatMap(row => {
|
|
274
313
|
const state = row.getAttribute('data-prts-session-state')
|
|
275
|
-
if (state !== 'ongoing' && state !== 'done') return []
|
|
314
|
+
if (state !== 'warning' && state !== 'ongoing' && state !== 'done') return []
|
|
276
315
|
const title = row.querySelector('[data-prts-row-title]')?.textContent.trim()
|
|
277
|
-
|
|
316
|
+
const rowKey = row.getAttribute('data-row-key')
|
|
317
|
+
const id = row.getAttribute('data-session-id') || (rowKey?.startsWith('session:') ? rowKey.slice(8) : title)
|
|
318
|
+
return title ? [{ id, title, state }] : []
|
|
278
319
|
})
|
|
320
|
+
const rows = [...fromService]
|
|
321
|
+
const statePriority = { done: 1, ongoing: 2, warning: 3 }
|
|
322
|
+
for (const nativeRow of nativeRows) {
|
|
323
|
+
const index = rows.findIndex(item => item.id === nativeRow.id || item.title === nativeRow.title)
|
|
324
|
+
if (index === -1) {
|
|
325
|
+
rows.push(nativeRow)
|
|
326
|
+
} else if (statePriority[nativeRow.state] > statePriority[rows[index].state]) {
|
|
327
|
+
rows[index] = { ...rows[index], state: nativeRow.state }
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
const warning = rows.filter(item => item.state === 'warning')
|
|
279
331
|
const ongoing = rows.filter(item => item.state === 'ongoing')
|
|
280
332
|
const done = rows.filter(item => item.state === 'done')
|
|
281
333
|
const signature = JSON.stringify({
|
|
334
|
+
warning: warning.map(item => [item.id, item.title, item.statusLabel]),
|
|
282
335
|
ongoing: ongoing.map(item => [item.id, item.title]),
|
|
283
336
|
done: done.map(item => [item.id, item.title]),
|
|
284
337
|
})
|
|
@@ -294,10 +347,11 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
294
347
|
}
|
|
295
348
|
const labelHidden = Array.from(label.classList).some(name => /hidden/i.test(name))
|
|
296
349
|
summaryRoot.toggleAttribute('data-prts-summary-search-hidden', labelHidden)
|
|
297
|
-
summaryRoot.hidden = ongoing.length === 0 && done.length === 0
|
|
350
|
+
summaryRoot.hidden = warning.length === 0 && ongoing.length === 0 && done.length === 0
|
|
298
351
|
if (signature === summarySignature) return
|
|
299
352
|
summarySignature = signature
|
|
300
353
|
summaryRoot.replaceChildren()
|
|
354
|
+
if (warning.length) summaryRoot.append(buildSummaryGroup('warning', '等待处理的会话', warning))
|
|
301
355
|
if (ongoing.length) summaryRoot.append(buildSummaryGroup('ongoing', '运行中的会话', ongoing))
|
|
302
356
|
if (done.length) summaryRoot.append(buildSummaryGroup('done', '完成未查看', done))
|
|
303
357
|
}
|
|
@@ -366,6 +420,7 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
366
420
|
}
|
|
367
421
|
|
|
368
422
|
function scan() {
|
|
423
|
+
connectSessionStatus()
|
|
369
424
|
const root = document?.querySelector?.('[data-prts-region="sessions"] [data-slot="sidebar.workspaces"]')
|
|
370
425
|
const next = new Set()
|
|
371
426
|
const nextVectorOwners = new Set()
|
|
@@ -509,6 +564,9 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
509
564
|
stopSessionList = () => {}
|
|
510
565
|
stopWorkspaceList()
|
|
511
566
|
stopWorkspaceList = () => {}
|
|
567
|
+
stopSessionStatus()
|
|
568
|
+
stopSessionStatus = () => {}
|
|
569
|
+
sessionStatus = undefined
|
|
512
570
|
statusSourcesStarted = false
|
|
513
571
|
if (scanFrame !== undefined) {
|
|
514
572
|
if (window?.cancelAnimationFrame) window.cancelAnimationFrame(scanFrame)
|
|
@@ -104,6 +104,11 @@ html[data-dsh-prts] [data-prts-session-summary-group="ongoing"] {
|
|
|
104
104
|
color: var(--prts-summary-state-color);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
html[data-dsh-prts] [data-prts-session-summary-group="warning"] {
|
|
108
|
+
--prts-summary-state-color: var(--dsw-alias-state-warn-primary, var(--prts-yellow));
|
|
109
|
+
color: var(--prts-summary-state-color);
|
|
110
|
+
}
|
|
111
|
+
|
|
107
112
|
html[data-dsh-prts] [data-prts-session-summary-group="done"] {
|
|
108
113
|
--prts-summary-state-color: var(--dsw-alias-state-success-primary, var(--prts-green));
|
|
109
114
|
color: var(--prts-summary-state-color);
|
|
@@ -148,6 +153,24 @@ html[data-dsh-prts] [data-prts-session-summary-signal="done"]::before {
|
|
|
148
153
|
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
|
|
149
154
|
}
|
|
150
155
|
|
|
156
|
+
html[data-dsh-prts] [data-prts-session-summary-signal="warning"]::before {
|
|
157
|
+
content: "";
|
|
158
|
+
position: absolute;
|
|
159
|
+
inset: 0;
|
|
160
|
+
border: 1px solid currentColor;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
html[data-dsh-prts] [data-prts-session-summary-signal="warning"]::after {
|
|
164
|
+
content: "";
|
|
165
|
+
position: absolute;
|
|
166
|
+
top: 2px;
|
|
167
|
+
left: 4px;
|
|
168
|
+
width: 1px;
|
|
169
|
+
height: 3px;
|
|
170
|
+
background: currentColor;
|
|
171
|
+
box-shadow: 0 3px currentColor;
|
|
172
|
+
}
|
|
173
|
+
|
|
151
174
|
html[data-dsh-prts] [data-prts-session-summary-popover] {
|
|
152
175
|
position: absolute;
|
|
153
176
|
z-index: 40;
|
|
@@ -241,6 +264,13 @@ html[data-dsh-prts] [data-prts-session-summary-item] > span:not([data-prts-sessi
|
|
|
241
264
|
white-space: nowrap;
|
|
242
265
|
}
|
|
243
266
|
|
|
267
|
+
html[data-dsh-prts] [data-prts-session-summary-item-status] {
|
|
268
|
+
flex: 0 0 auto;
|
|
269
|
+
margin-left: auto;
|
|
270
|
+
color: var(--prts-summary-state-color);
|
|
271
|
+
font: 700 9px/1 var(--prts-mono);
|
|
272
|
+
}
|
|
273
|
+
|
|
244
274
|
html[data-dsh-prts] [data-prts-session-summary-item]:is(:hover, :focus-visible) {
|
|
245
275
|
background: color-mix(in srgb, currentColor 9%, transparent);
|
|
246
276
|
}
|
package/src/styles/prts.css
CHANGED
|
@@ -976,6 +976,10 @@ html[data-dsh-prts] [data-prts-row-title] {
|
|
|
976
976
|
white-space: nowrap;
|
|
977
977
|
}
|
|
978
978
|
|
|
979
|
+
html[data-dsh-prts] [data-prts-session-row] > span:has(> [data-state]) {
|
|
980
|
+
padding-left: 0 !important;
|
|
981
|
+
}
|
|
982
|
+
|
|
979
983
|
html[data-dsh-prts] [data-prts-session-row] [data-prts-row-title]::before {
|
|
980
984
|
content: attr(data-prts-session-index);
|
|
981
985
|
margin-right: 8px;
|
|
@@ -1109,6 +1113,13 @@ html[data-dsh-prts] [data-conversation-scroll] {
|
|
|
1109
1113
|
z-index: 2;
|
|
1110
1114
|
}
|
|
1111
1115
|
|
|
1116
|
+
/* DSH renders transcript width handles beside the scroll surface. Its scroll
|
|
1117
|
+
surface needs this layer for our ambient backdrop, but must not cover the
|
|
1118
|
+
native handles' hit areas. Keep DSH's higher dragging layer intact. */
|
|
1119
|
+
html[data-dsh-prts] [data-width-handle]:not([data-dragging]) {
|
|
1120
|
+
z-index: 3;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1112
1123
|
html[data-dsh-prts][data-prts-conversation-style="native"] [data-message-role="user"],
|
|
1113
1124
|
html[data-dsh-prts][data-prts-conversation-style="native"] [data-chat-flow-kind="user"] {
|
|
1114
1125
|
position: relative;
|
|
@@ -1270,7 +1281,7 @@ html[data-dsh-prts][data-prts-conversation-style="deck-chat"] [data-message-role
|
|
|
1270
1281
|
--prts-chat-link-x: -34px;
|
|
1271
1282
|
position: relative;
|
|
1272
1283
|
width: calc(100% - 56px);
|
|
1273
|
-
margin-inline-start: calc((100% - min(748px, 100%)) / 2 + 56px);
|
|
1284
|
+
margin-inline-start: calc((100% - min(var(--dsh-chat-content-width, 748px), 100%)) / 2 + 56px);
|
|
1274
1285
|
padding: 16px 22px !important;
|
|
1275
1286
|
border: 1px solid var(--prts-chat-assistant-edge) !important;
|
|
1276
1287
|
border-radius: 6px 18px 18px 18px !important;
|
|
@@ -437,7 +437,7 @@ html[data-dsh-prts] [data-prts-hero-active] [data-phase="hero"] {
|
|
|
437
437
|
|
|
438
438
|
html[data-dsh-prts] [data-prts-hero-active] [data-composer-seat] {
|
|
439
439
|
grid-row: 2;
|
|
440
|
-
width: min(calc(
|
|
440
|
+
width: min(calc(var(--dsh-chat-content-width, 748px) + 64px), 100%);
|
|
441
441
|
min-width: 0 !important;
|
|
442
442
|
align-self: end;
|
|
443
443
|
justify-self: center;
|