@sparkelf/dsh-patch-session-log-trajectory-toolbar 0.1.0-rc.12

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DeepSeek
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,6 @@
1
+ # Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
2
+ # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
+ # after editing either side, bring the other along and re-record with:
4
+ # pnpm run verify-translation-pairing --write patches/npm/session-log-trajectory-toolbar/README.md
5
+ README.md: 414f4ece3e88076335d794cedbe8489302774791
6
+ README.zh.md: 2215fca8e2a5c6167f34aa92115cc12fea509a9f
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # @sparkelf/dsh-patch-session-log-trajectory-toolbar
2
+
3
+ English | [中文](README.zh.md)
4
+
5
+ This data-only package places the official Session-log download action immediately before Trajectory search on desktop screens. The action uses the Trajectory toolbar's compact height, typography, colors, hover state, and focus treatment instead of the Session Header capsule. Screens up to 767 px retain the official Header position and styling.
6
+
7
+ The payload adds one typed Trajectory toolbar utility slot and registers a second presentation of the existing Session-log action into it. Both presentations use the same download controller, request, state, and dialog; the package does not add another export path or archive implementation.
8
+
9
+ The target is exact official source revision `0a53fb55bea101816fa226bb964ae2bed71c343b`. The payload is applied before that source tree is built. The package has no JavaScript entry, lifecycle script, Cordis plugin, compatibility adapter, or alternate variant.
10
+
11
+ Retire this package when official DSH exposes an equivalent Trajectory toolbar utility slot and places Session export before search on desktop while retaining the Header action on phones.
package/README.zh.md ADDED
@@ -0,0 +1,11 @@
1
+ # @sparkelf/dsh-patch-session-log-trajectory-toolbar
2
+
3
+ [English](README.md) | 中文
4
+
5
+ 该data-only package在桌面屏幕上把official会话日志下载操作放到Trajectory搜索框紧邻左侧。该操作使用Trajectory toolbar的紧凑高度、字体、颜色、hover状态与focus样式,不再使用Session Header胶囊样式。宽度不超过767 px的屏幕保留official Header位置及样式。
6
+
7
+ payload增加一个typed Trajectory toolbar utility slot,并把既有会话日志操作的第二个presentation注册进该slot。两个presentation共用同一个download controller、request、state与dialog;本package不增加第二条export path或archive implementation。
8
+
9
+ target是exact official source revision `0a53fb55bea101816fa226bb964ae2bed71c343b`,payload在该source tree build前应用。本package没有JavaScript entry、lifecycle script、Cordis plugin、compatibility adapter或alternate variant。
10
+
11
+ official DSH暴露等价Trajectory toolbar utility slot,并在桌面端把Session export放到搜索框前、同时在手机上保留Header操作后,retire本package。
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "description": "Data-only exact official-source patch placing Session export in the desktop Trajectory toolbar",
3
+ "dshPatch": {
4
+ "formatVersion": 1,
5
+ "variants": [
6
+ {
7
+ "dsh": ">=0.1.2-alpha.2",
8
+ "file": "./patches/session-log-trajectory-toolbar.patch",
9
+ "id": "session-log-desktop-trajectory-toolbar",
10
+ "target": {
11
+ "baseRevision": "0a53fb55bea101816fa226bb964ae2bed71c343b",
12
+ "kind": "dsh-source",
13
+ "paths": [
14
+ "packages/client/ui-trajectory/",
15
+ "packages/session-query/session-log-export/"
16
+ ]
17
+ }
18
+ }
19
+ ]
20
+ },
21
+ "files": [
22
+ "patches/*.patch"
23
+ ],
24
+ "license": "MIT",
25
+ "name": "@sparkelf/dsh-patch-session-log-trajectory-toolbar",
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "repository": {
30
+ "directory": "patches/npm/session-log-trajectory-toolbar",
31
+ "type": "git",
32
+ "url": "git+https://github.com/SparkElf/deepseek-harness-plus.git"
33
+ },
34
+ "type": "module",
35
+ "version": "0.1.0-rc.12"
36
+ }
@@ -0,0 +1,305 @@
1
+ diff --git a/packages/client/ui-trajectory/src/client/TrajectoryToolbar.module.css b/packages/client/ui-trajectory/src/client/TrajectoryToolbar.module.css
2
+ index aa386504113dbb6db3afd3d3eb72d51b4a8ad71f..6f6c5343b115bb39845bbf774ad52a871922922e 100644
3
+ --- a/packages/client/ui-trajectory/src/client/TrajectoryToolbar.module.css
4
+ +++ b/packages/client/ui-trajectory/src/client/TrajectoryToolbar.module.css
5
+ @@ -164,13 +164,19 @@
6
+ font: 14px/14px var(--ds-font-family-code);
7
+ }
8
+
9
+ +.utilities {
10
+ + display: flex;
11
+ + flex: none;
12
+ + align-items: center;
13
+ + margin-left: auto;
14
+ +}
15
+ +
16
+ .search {
17
+ display: flex;
18
+ flex: 0 1 164px;
19
+ align-items: center;
20
+ min-width: 84px;
21
+ height: 22px;
22
+ - margin-left: auto;
23
+ padding: 0 6px;
24
+ gap: 4px;
25
+ border: 1px solid var(--dsw-alias-border-l2);
26
+ diff --git a/packages/client/ui-trajectory/src/client/TrajectoryToolbar.tsx b/packages/client/ui-trajectory/src/client/TrajectoryToolbar.tsx
27
+ index 92d7ce9ab07211d6a58c24e20a428381b7c4b61d..dfbc88f1e3aeb0e1e08fed4c7947150693dbcde5 100644
28
+ --- a/packages/client/ui-trajectory/src/client/TrajectoryToolbar.tsx
29
+ +++ b/packages/client/ui-trajectory/src/client/TrajectoryToolbar.tsx
30
+ @@ -1,5 +1,6 @@
31
+ /** Trajectory toolbar: timeline and ledger fold controls. */
32
+
33
+ +import type { ReactNode } from 'react'
34
+ import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'
35
+ import { IconSearchOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
36
+ import type { NS } from './locales.ts'
37
+ @@ -26,6 +27,8 @@ export interface TrajectoryToolbarProps {
38
+ searchQuery: string
39
+ /** Update the live ledger search query. */
40
+ onSearchQueryChange: (query: string) => void
41
+ + /** Session utilities contributed immediately before search. */
42
+ + utilities: ReactNode
43
+ /** Translate a toolbar dictionary key. */
44
+ t: TranslateNS<typeof NS>
45
+ }
46
+ @@ -46,6 +49,7 @@ export function TrajectoryToolbar({
47
+ onToggleAllAssistants,
48
+ searchQuery,
49
+ onSearchQueryChange,
50
+ + utilities,
51
+ t,
52
+ }: TrajectoryToolbarProps) {
53
+ return (
54
+ @@ -111,7 +115,8 @@ export function TrajectoryToolbar({
55
+ {t('toolbar.calls')}
56
+ </button>
57
+ </div>
58
+ - <div className={css.search}>
59
+ + <div className={css.utilities} data-trajectory-toolbar-utilities="">{utilities}</div>
60
+ + <div className={css.search} data-trajectory-search="">
61
+ <IconSearchOutline16 size={11} className={css.searchIcon} />
62
+ <input
63
+ type="search"
64
+ diff --git a/packages/client/ui-trajectory/src/client/TrajectoryView.tsx b/packages/client/ui-trajectory/src/client/TrajectoryView.tsx
65
+ index 2ac0d5ddf124714e459c72a99d7eb699fa62d3bd..ace4e584fb8b3922378c9e297ec58c64561e7c55 100644
66
+ --- a/packages/client/ui-trajectory/src/client/TrajectoryView.tsx
67
+ +++ b/packages/client/ui-trajectory/src/client/TrajectoryView.tsx
68
+ @@ -121,7 +121,9 @@ export function TrajectoryView({
69
+ useSession, useTrajectory, useDuration, loadOlder, loadImage, setActualDuration,
70
+ viewRequest, completeViewRequest, renderSlot, t,
71
+ }: ConvViewProps
72
+ - & PropsRenderSlots<'conversation.trajectory.images'>
73
+ + & PropsRenderSlots<
74
+ + 'conversation.trajectory.images' | 'conversation.trajectory.toolbar.utilities'
75
+ + >
76
+ & InjectFace<TrajectoryViewInjected>
77
+ & PropsLocale<'trajectory'>) {
78
+ const [collapsedTurns, setCollapsedTurns] = useState<ReadonlySet<number>>(EMPTY_TURN_IDS)
79
+ @@ -471,6 +473,7 @@ export function TrajectoryView({
80
+ onToggleAllAssistants={toggleAllAssistants}
81
+ searchQuery={searchQuery}
82
+ onSearchQueryChange={setSearchQuery}
83
+ + utilities={renderSlot('conversation.trajectory.toolbar.utilities', {})}
84
+ t={t}
85
+ />
86
+ <TrajectoryTimeline
87
+ diff --git a/packages/client/ui-trajectory/src/client/index.ts b/packages/client/ui-trajectory/src/client/index.ts
88
+ index 118f3b2c288730018fba6b97add0bf078b64062f..a8c71cf9ee2662870567355b4f44738fe7c1e3bd 100644
89
+ --- a/packages/client/ui-trajectory/src/client/index.ts
90
+ +++ b/packages/client/ui-trajectory/src/client/index.ts
91
+ @@ -36,6 +36,13 @@ export type {
92
+ UseTrajectory,
93
+ } from './trajectory-contract.ts'
94
+
95
+ +declare module '@deepseek-ai/dsh-client-ui-slots' {
96
+ + interface SlotMap {
97
+ + /** Compact Session utilities immediately before the Trajectory search field. */
98
+ + 'conversation.trajectory.toolbar.utilities': { kind: 'list'; scope: 'session' }
99
+ + }
100
+ +}
101
+ +
102
+ /** Required services: the conversation slot, registries, ordinary Session paging, and the locale service. */
103
+ export const inject = ['slots', 'sessions', 'uiSession', 'uiConversation', 'locale']
104
+
105
+ @@ -82,6 +89,7 @@ export function apply(ctx: Context): void {
106
+ label: () => t('view.trajectory'),
107
+ children: {
108
+ 'conversation.trajectory.images': { kind: 'single', scope: 'session' },
109
+ + 'conversation.trajectory.toolbar.utilities': { kind: 'list', scope: 'session' },
110
+ },
111
+ inject: (sessionId: SessionId): TrajectoryViewInjected => {
112
+ const session = ctx.sessions.binding(sessionId)?.session
113
+ diff --git a/packages/session-query/session-log-export/package.json b/packages/session-query/session-log-export/package.json
114
+ index 60cba7ebdd3fbff86223db0f482380f198ff83e1..a717c25ae3af88e2286afe7d58f43d4ff71bcdc5 100644
115
+ --- a/packages/session-query/session-log-export/package.json
116
+ +++ b/packages/session-query/session-log-export/package.json
117
+ @@ -60,6 +60,7 @@
118
+ "@deepseek-ai/dsh-client-ui-conversation": "workspace:^",
119
+ "@deepseek-ai/dsh-client-ui-renderer": "workspace:^",
120
+ "@deepseek-ai/dsh-client-ui-session": "workspace:^",
121
+ + "@deepseek-ai/dsh-client-ui-trajectory": "workspace:^",
122
+ "@deepseek-ai/dsh-client-ui-primitives": "workspace:^",
123
+ "@deepseek-ai/dsh-client-ui-slots": "workspace:^",
124
+ "@deepseek-ai/dsh-commands": "workspace:^",
125
+ @@ -77,7 +78,8 @@
126
+ "@deepseek-ai/dsh-client-ui-commands",
127
+ "@deepseek-ai/dsh-client-ui-conversation",
128
+ "@deepseek-ai/dsh-client-ui-renderer",
129
+ - "@deepseek-ai/dsh-client-ui-session"
130
+ + "@deepseek-ai/dsh-client-ui-session",
131
+ + "@deepseek-ai/dsh-client-ui-trajectory"
132
+ ],
133
+ "platform": "web"
134
+ }
135
+ diff --git a/packages/session-query/session-log-export/src/client/HeaderAction.module.css b/packages/session-query/session-log-export/src/client/HeaderAction.module.css
136
+ index 288e7f9bae4b7b103c5ce52dfbc4292437fa7d83..8007563465a27cfd556f185a5042aa8878cc92d1 100644
137
+ --- a/packages/session-query/session-log-export/src/client/HeaderAction.module.css
138
+ +++ b/packages/session-query/session-log-export/src/client/HeaderAction.module.css
139
+ @@ -34,3 +34,52 @@
140
+ .sessionLogButton span {
141
+ white-space: nowrap;
142
+ }
143
+ +
144
+ +.trajectoryButton {
145
+ + display: none;
146
+ + flex: none;
147
+ + align-items: center;
148
+ + height: 22px;
149
+ + padding: 0 6px;
150
+ + gap: 4px;
151
+ + border: 0;
152
+ + border-radius: 3px;
153
+ + color: var(--dsw-alias-label-tertiary);
154
+ + background: transparent;
155
+ + cursor: pointer;
156
+ + font: var(--dsw-font-xxs-12);
157
+ +}
158
+ +
159
+ +.trajectoryButton:hover:not(:disabled) {
160
+ + color: var(--dsw-alias-label-primary);
161
+ + background: var(--dsw-alias-interactive-bg-hover);
162
+ +}
163
+ +
164
+ +.trajectoryButton:focus-visible {
165
+ + outline: 1px solid var(--dsw-alias-state-business-primary);
166
+ + outline-offset: 1px;
167
+ +}
168
+ +
169
+ +.trajectoryButton:disabled {
170
+ + color: var(--dsw-alias-label-dimmed);
171
+ + cursor: wait;
172
+ +}
173
+ +
174
+ +.trajectoryButton span,
175
+ +.trajectoryButton svg {
176
+ + flex: none;
177
+ +}
178
+ +
179
+ +.trajectoryButton span {
180
+ + white-space: nowrap;
181
+ +}
182
+ +
183
+ +@media (min-width: 768px) {
184
+ + .sessionLogButton {
185
+ + display: none;
186
+ + }
187
+ +
188
+ + .trajectoryButton {
189
+ + display: inline-flex;
190
+ + }
191
+ +}
192
+ diff --git a/packages/session-query/session-log-export/src/client/HeaderAction.tsx b/packages/session-query/session-log-export/src/client/HeaderAction.tsx
193
+ index 7adc40aa5cde8d3b25e2168ea49b630e2fe6af83..3a6dd6fa9bcd82418184dda0938f377bd7347789 100644
194
+ --- a/packages/session-query/session-log-export/src/client/HeaderAction.tsx
195
+ +++ b/packages/session-query/session-log-export/src/client/HeaderAction.tsx
196
+ @@ -1,8 +1,16 @@
197
+ import type { ReactNode } from 'react'
198
+ import { IconDownloadOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
199
+ +import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'
200
+ import { SessionLogDownloadDialog, type SessionLogDownloadDialogProps } from './Dialog.tsx'
201
+ +import type { SessionLogDownloadDialogInjected } from './Dialog.tsx'
202
+ +import { NS } from './locales.ts'
203
+ import css from './HeaderAction.module.css'
204
+
205
+ +type SessionLogDownloadToolbarActionProps =
206
+ + PropsRuntime<'conversation.trajectory.toolbar.utilities'>
207
+ + & PropsLocale<typeof NS>
208
+ + & InjectFace<SessionLogDownloadDialogInjected>
209
+ +
210
+ /**
211
+ * Render the Session Header export capsule and its shared result dialog.
212
+ * @param props - Session runtime, download controller, and localized dialog copy.
213
+ @@ -29,3 +37,30 @@ export function SessionLogDownloadHeaderAction(props: SessionLogDownloadDialogPr
214
+ </>
215
+ )
216
+ }
217
+ +
218
+ +/**
219
+ + * Render the desktop Session export action in the Trajectory toolbar.
220
+ + * @param props - Session runtime, shared download controller, and localized copy.
221
+ + * @returns the compact toolbar action.
222
+ + */
223
+ +export function SessionLogDownloadToolbarAction(
224
+ + props: SessionLogDownloadToolbarActionProps,
225
+ +): ReactNode {
226
+ + const { sessionId, useSessionLogDownload, request, t } = props
227
+ + const entry = useSessionLogDownload(state => state.bySession[String(sessionId)])
228
+ + const busy = entry?.status === 'downloading'
229
+ +
230
+ + return (
231
+ + <button
232
+ + type="button"
233
+ + className={css.trajectoryButton}
234
+ + disabled={busy}
235
+ + aria-busy={busy}
236
+ + title={t('header.action')}
237
+ + onClick={() => { void request(sessionId) }}
238
+ + >
239
+ + <IconDownloadOutline16 size={11} />
240
+ + <span>{t('header.action')}</span>
241
+ + </button>
242
+ + )
243
+ +}
244
+ diff --git a/packages/session-query/session-log-export/src/client/index.ts b/packages/session-query/session-log-export/src/client/index.ts
245
+ index 97187311fad4ab6f021fc298b8205dd529b9af37..a6ca23e3b3ec1ded2a21d3428990261f7d7da0c4 100644
246
+ --- a/packages/session-query/session-log-export/src/client/index.ts
247
+ +++ b/packages/session-query/session-log-export/src/client/index.ts
248
+ @@ -7,9 +7,12 @@ import type {} from '@deepseek-ai/dsh-client-ui-commands/client'
249
+ import type {} from '@deepseek-ai/dsh-client-ui-conversation/client'
250
+ import type {} from '@deepseek-ai/dsh-client-ui-renderer/client'
251
+ import type {} from '@deepseek-ai/dsh-client-ui-session/client'
252
+ +import type {} from '@deepseek-ai/dsh-client-ui-trajectory/client'
253
+ import { SessionLogDownloadController } from './controller.ts'
254
+ import type { SessionLogDownloadDialogInjected } from './Dialog.tsx'
255
+ -import { SessionLogDownloadHeaderAction } from './HeaderAction.tsx'
256
+ +import {
257
+ + SessionLogDownloadHeaderAction, SessionLogDownloadToolbarAction,
258
+ +} from './HeaderAction.tsx'
259
+ import { en, NS, zh, type SessionLogDownloadKey } from './locales.ts'
260
+
261
+ declare module '@deepseek-ai/cordis' {
262
+ @@ -34,6 +37,11 @@ export const inject = ['slots', 'locale']
263
+ */
264
+ export function apply(ctx: ClientContext): void {
265
+ const controller = new SessionLogDownloadController()
266
+ + const injectAction = (): SessionLogDownloadDialogInjected => ({
267
+ + hooks: { sessionLogDownload: controller.store },
268
+ + request: (sessionId: SessionId) => controller.download(sessionId),
269
+ + dismiss: (sessionId: SessionId) => { controller.dismiss(sessionId) },
270
+ + })
271
+ ctx.provide('sessionLogDownload', controller)
272
+ ctx.effect(() => async () => { await controller.dispose() }, 'session-log-download: browser download lifecycle')
273
+ ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'session-log-download: browser dictionaries')
274
+ @@ -44,12 +52,14 @@ export function apply(ctx: ClientContext): void {
275
+ name: 'conversation.session.header.utilities',
276
+ id: 'session-log-download',
277
+ locale: NS,
278
+ - inject: (): SessionLogDownloadDialogInjected => ({
279
+ - hooks: { sessionLogDownload: controller.store },
280
+ - request: (sessionId: SessionId) => controller.download(sessionId),
281
+ - dismiss: (sessionId: SessionId) => { controller.dismiss(sessionId) },
282
+ - }),
283
+ + inject: injectAction,
284
+ }, SessionLogDownloadHeaderAction))
285
+ + ctx.slots.inject('conversation.trajectory.toolbar.utilities', () => ctx.slots.register({
286
+ + name: 'conversation.trajectory.toolbar.utilities',
287
+ + id: 'session-log-download',
288
+ + locale: NS,
289
+ + inject: injectAction,
290
+ + }, SessionLogDownloadToolbarAction))
291
+ }
292
+
293
+ export type { SessionLogDownloadDialogInjected, SessionLogDownloadDialogProps } from './Dialog.tsx'
294
+ diff --git a/packages/session-query/session-log-export/tsconfig.client.json b/packages/session-query/session-log-export/tsconfig.client.json
295
+ index 6e3e746c4c58753b3023f94ed4c872e5f1ac1d51..c5e2c7b69c41289d2db3be1753c5bb3030be87d8 100644
296
+ --- a/packages/session-query/session-log-export/tsconfig.client.json
297
+ +++ b/packages/session-query/session-log-export/tsconfig.client.json
298
+ @@ -23,6 +23,7 @@
299
+ { "path": "../../client/ui-renderer" },
300
+ { "path": "../../client/ui-session" },
301
+ { "path": "../../client/ui-slots" },
302
+ + { "path": "../../client/ui-trajectory" },
303
+ { "path": "../../core/session" }
304
+ ]
305
+ }