@benz-ai-x/dsh-md-preview 0.7.2 → 0.10.0
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/README.md +5 -3
- package/README.zh.md +6 -3
- package/lib/client.js +910 -525
- package/lib/index.js +102 -3
- package/lib/typert/remote-client.js +47 -0
- package/lib/types/client/DocumentIcon.d.ts +7 -0
- package/lib/types/client/PanelToggle.d.ts +10 -0
- package/lib/types/client/PreviewOverlay.d.ts +21 -4
- package/lib/types/client/WorkspaceBrowser.d.ts +30 -17
- package/lib/types/client/WorkspaceDocsAction.d.ts +27 -15
- package/lib/types/client/document-path.d.ts +6 -0
- package/lib/types/client/leave-intent.d.ts +31 -0
- package/lib/types/client/locale.d.ts +26 -2
- package/lib/types/client/outline.d.ts +2 -0
- package/lib/types/client/panel-dock.d.ts +32 -0
- package/lib/types/client/preferences.d.ts +63 -0
- package/lib/types/client/preview-session.d.ts +5 -7
- package/lib/types/client/reading.d.ts +97 -0
- package/lib/types/client/turn-files.d.ts +48 -0
- package/lib/types/client/use-panel-dock.d.ts +8 -0
- package/lib/types/client/use-preview-session.d.ts +0 -2
- package/lib/types/config.d.ts +6 -0
- package/lib/types/constants.d.ts +8 -0
- package/lib/types/index.d.ts +2 -2
- package/lib/types/protocol.d.ts +27 -0
- package/lib/types/remote.d.ts +18 -1
- package/lib/types/typert/remote-client.d.ts +3 -1
- package/package.json +1 -1
- package/lib/types/client/FileManagerAction.d.ts +0 -31
- package/lib/types/client/SideBrowser.d.ts +0 -43
- package/lib/types/client/WorkspaceDocsDock.d.ts +0 -40
- package/lib/types/client/WorkspaceDocsView.d.ts +0 -29
package/lib/index.js
CHANGED
|
@@ -12,6 +12,14 @@ const DEFAULT_PREVIEW_EXTENSIONS = [
|
|
|
12
12
|
".markdown",
|
|
13
13
|
".txt"
|
|
14
14
|
];
|
|
15
|
+
/** Default search result cap: far above real agent-workspace document counts
|
|
16
|
+
* (tens to low hundreds observed in DSH sessions) while bounding one answer. */
|
|
17
|
+
const DEFAULT_SEARCH_MAX_RESULTS = 200;
|
|
18
|
+
/** Default search traversal cap in directories: bounded for any deployment
|
|
19
|
+
* workspace; a pathological tree reports `traversal-limit`, never hangs. */
|
|
20
|
+
const DEFAULT_SEARCH_MAX_DIRECTORIES = 2e3;
|
|
21
|
+
/** Default parallel `listDir` width for one search. */
|
|
22
|
+
const DEFAULT_SEARCH_CONCURRENCY = 8;
|
|
15
23
|
//#endregion
|
|
16
24
|
//#region src/remote.ts
|
|
17
25
|
var __runInitializers = function(thisArg, initializers, value) {
|
|
@@ -96,12 +104,14 @@ let MdPreviewService = (() => {
|
|
|
96
104
|
let _read_decorators;
|
|
97
105
|
let _write_decorators;
|
|
98
106
|
let _list_decorators;
|
|
107
|
+
let _search_decorators;
|
|
99
108
|
return class MdPreviewService extends _classSuper {
|
|
100
109
|
static {
|
|
101
110
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
102
111
|
_read_decorators = [Remote];
|
|
103
112
|
_write_decorators = [Remote];
|
|
104
113
|
_list_decorators = [Remote];
|
|
114
|
+
_search_decorators = [Remote];
|
|
105
115
|
__esDecorate(this, null, _read_decorators, {
|
|
106
116
|
kind: "method",
|
|
107
117
|
name: "read",
|
|
@@ -135,6 +145,17 @@ let MdPreviewService = (() => {
|
|
|
135
145
|
},
|
|
136
146
|
metadata: _metadata
|
|
137
147
|
}, null, _instanceExtraInitializers);
|
|
148
|
+
__esDecorate(this, null, _search_decorators, {
|
|
149
|
+
kind: "method",
|
|
150
|
+
name: "search",
|
|
151
|
+
static: false,
|
|
152
|
+
private: false,
|
|
153
|
+
access: {
|
|
154
|
+
has: (obj) => "search" in obj,
|
|
155
|
+
get: (obj) => obj.search
|
|
156
|
+
},
|
|
157
|
+
metadata: _metadata
|
|
158
|
+
}, null, _instanceExtraInitializers);
|
|
138
159
|
if (_metadata) Object.defineProperty(this, Symbol.metadata, {
|
|
139
160
|
enumerable: true,
|
|
140
161
|
configurable: true,
|
|
@@ -262,6 +283,78 @@ let MdPreviewService = (() => {
|
|
|
262
283
|
};
|
|
263
284
|
}
|
|
264
285
|
/**
|
|
286
|
+
* Search previewable documents by name across the whole session workspace,
|
|
287
|
+
* including directories the browser face never expanded. First-version
|
|
288
|
+
* semantics: case-insensitive substring match on the entry name. The walk
|
|
289
|
+
* stays inside the session authority (root resolve + containment, visited
|
|
290
|
+
* dedupe so links cannot loop it), never reads file bodies, and reports
|
|
291
|
+
* honestly whether the answer is complete — a permission failure, a
|
|
292
|
+
* traversal bound, or the result cap each mark it incomplete with the
|
|
293
|
+
* matching limit.
|
|
294
|
+
* @param sessionId - owning session; its header cwd roots the walk.
|
|
295
|
+
* @param query - raw search text; matched case-insensitively against names.
|
|
296
|
+
* @param signal - caller cancellation carried through every fs call.
|
|
297
|
+
* @returns the query, its matches with workspace-relative paths, and
|
|
298
|
+
* whether the walk finished whole.
|
|
299
|
+
* @throws RemoteError with a stable MdPreview failure code.
|
|
300
|
+
*/
|
|
301
|
+
async search(sessionId, query, signal) {
|
|
302
|
+
const q = query.trim().toLowerCase();
|
|
303
|
+
if (q.length === 0) throw failure("md-preview/bad-request", "mdPreview/search requires a non-empty query");
|
|
304
|
+
const { root } = await this.resolveContainedTarget(sessionId, "", signal, "search");
|
|
305
|
+
const rootPath = root.displayPath;
|
|
306
|
+
const previewable = [...this.config.allowedExtensions, ...this.config.previewExtensions];
|
|
307
|
+
const matches = [];
|
|
308
|
+
const limits = /* @__PURE__ */ new Set();
|
|
309
|
+
const visited = /* @__PURE__ */ new Set([rootPath]);
|
|
310
|
+
let frontier = [root];
|
|
311
|
+
while (frontier.length > 0) {
|
|
312
|
+
if (signal.aborted) throw new DOMException("aborted", "AbortError");
|
|
313
|
+
const batch = frontier.splice(0, this.config.searchConcurrency);
|
|
314
|
+
const listings = await Promise.all(batch.map(async (dir) => {
|
|
315
|
+
try {
|
|
316
|
+
return { entries: await this.ctx.fs.listDir(dir, signal) };
|
|
317
|
+
} catch (error) {
|
|
318
|
+
if (signal.aborted) throw error;
|
|
319
|
+
return { entries: null };
|
|
320
|
+
}
|
|
321
|
+
}));
|
|
322
|
+
for (const { entries } of listings) {
|
|
323
|
+
if (entries === null) {
|
|
324
|
+
limits.add("directory-failure");
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
for (const entry of entries) {
|
|
328
|
+
if (entry.type === "file" && entry.name.toLowerCase().includes(q) && isAllowedExtension(entry.name, previewable)) matches.push({
|
|
329
|
+
name: entry.name,
|
|
330
|
+
path: workspaceRelative(rootPath, entry.target.displayPath, entry.name)
|
|
331
|
+
});
|
|
332
|
+
if (entry.type !== "directory") continue;
|
|
333
|
+
const child = entry.target.displayPath;
|
|
334
|
+
if (visited.has(child) || !this.ctx.fs.contains(root, entry.target)) continue;
|
|
335
|
+
if (visited.size >= this.config.searchMaxDirectories) {
|
|
336
|
+
limits.add("traversal-limit");
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
visited.add(child);
|
|
340
|
+
frontier.push(entry.target);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
if (matches.length >= this.config.searchMaxResults) {
|
|
344
|
+
limits.add("result-limit");
|
|
345
|
+
matches.length = this.config.searchMaxResults;
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
matches.sort((a, b) => a.path.localeCompare(b.path));
|
|
350
|
+
return {
|
|
351
|
+
query,
|
|
352
|
+
matches,
|
|
353
|
+
complete: limits.size === 0,
|
|
354
|
+
limits: [...limits]
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
265
358
|
* The shared authority preamble of the remote methods: resolve a path to a
|
|
266
359
|
* live, contained, regular workspace file, or reject it with the stable
|
|
267
360
|
* failure code. One home for the check order and the aborted-rethrow
|
|
@@ -329,7 +422,10 @@ let MdPreviewService = (() => {
|
|
|
329
422
|
const Config = z.object({
|
|
330
423
|
maxBytes: z.number().min(1).default(DEFAULT_MAX_BYTES),
|
|
331
424
|
allowedExtensions: z.array(z.string()).default([...DEFAULT_ALLOWED_EXTENSIONS]),
|
|
332
|
-
previewExtensions: z.array(z.string()).default([...DEFAULT_PREVIEW_EXTENSIONS])
|
|
425
|
+
previewExtensions: z.array(z.string()).default([...DEFAULT_PREVIEW_EXTENSIONS]),
|
|
426
|
+
searchMaxResults: z.number().min(1).default(200),
|
|
427
|
+
searchMaxDirectories: z.number().min(1).default(DEFAULT_SEARCH_MAX_DIRECTORIES),
|
|
428
|
+
searchConcurrency: z.number().min(1).default(8)
|
|
333
429
|
});
|
|
334
430
|
//#endregion
|
|
335
431
|
//#region src/protocol.ts
|
|
@@ -363,11 +459,14 @@ const inject = [
|
|
|
363
459
|
function apply(ctx, config = {
|
|
364
460
|
maxBytes: DEFAULT_MAX_BYTES,
|
|
365
461
|
allowedExtensions: [...DEFAULT_ALLOWED_EXTENSIONS],
|
|
366
|
-
previewExtensions: [...DEFAULT_PREVIEW_EXTENSIONS]
|
|
462
|
+
previewExtensions: [...DEFAULT_PREVIEW_EXTENSIONS],
|
|
463
|
+
searchMaxResults: 200,
|
|
464
|
+
searchMaxDirectories: DEFAULT_SEARCH_MAX_DIRECTORIES,
|
|
465
|
+
searchConcurrency: 8
|
|
367
466
|
}) {
|
|
368
467
|
ctx.plugin(MdPreviewService, config);
|
|
369
468
|
}
|
|
370
469
|
//#endregion
|
|
371
|
-
export { Config, DEFAULT_ALLOWED_EXTENSIONS, DEFAULT_MAX_BYTES, DEFAULT_PREVIEW_EXTENSIONS, MD_PREVIEW_FAILURE_CODES, MdPreviewService, apply, inject, isAllowedExtension, name };
|
|
470
|
+
export { Config, DEFAULT_ALLOWED_EXTENSIONS, DEFAULT_MAX_BYTES, DEFAULT_PREVIEW_EXTENSIONS, DEFAULT_SEARCH_CONCURRENCY, DEFAULT_SEARCH_MAX_DIRECTORIES, DEFAULT_SEARCH_MAX_RESULTS, MD_PREVIEW_FAILURE_CODES, MdPreviewService, apply, inject, isAllowedExtension, name };
|
|
372
471
|
|
|
373
472
|
//# sourceMappingURL=index.js.map
|
|
@@ -38,6 +38,21 @@ const listResult$schema = z.object({
|
|
|
38
38
|
path: z.string(),
|
|
39
39
|
entries: z.array(listEntry$schema)
|
|
40
40
|
});
|
|
41
|
+
const searchQuery$schema = z.string().min(1);
|
|
42
|
+
const searchMatch$schema = z.object({
|
|
43
|
+
name: z.string(),
|
|
44
|
+
path: z.string()
|
|
45
|
+
});
|
|
46
|
+
const searchResult$schema = z.object({
|
|
47
|
+
query: z.string(),
|
|
48
|
+
matches: z.array(searchMatch$schema),
|
|
49
|
+
complete: z.boolean(),
|
|
50
|
+
limits: z.array(z.enum([
|
|
51
|
+
"directory-failure",
|
|
52
|
+
"traversal-limit",
|
|
53
|
+
"result-limit"
|
|
54
|
+
]))
|
|
55
|
+
});
|
|
41
56
|
/** The MdPreview contribution mounted by this package's browser entry. */
|
|
42
57
|
const TYPERT_REMOTE = {
|
|
43
58
|
package: "@benz-ai-x/dsh-md-preview",
|
|
@@ -170,6 +185,38 @@ const TYPERT_REMOTE = {
|
|
|
170
185
|
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/list:result",
|
|
171
186
|
schema: listResult$schema
|
|
172
187
|
}
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
id: "@benz-ai-x/dsh-md-preview#mdPreview/search",
|
|
191
|
+
service: "mdPreview",
|
|
192
|
+
namespace: "mdPreview",
|
|
193
|
+
method: "search",
|
|
194
|
+
invocation: { kind: "direct" },
|
|
195
|
+
parameters: [{
|
|
196
|
+
name: "sessionId",
|
|
197
|
+
wire: "sessionId",
|
|
198
|
+
source: "json",
|
|
199
|
+
codec: {
|
|
200
|
+
mode: "strict",
|
|
201
|
+
typeSymbol: "@deepseek-ai/dsh-session/types#SessionId",
|
|
202
|
+
schema: readSessionId$schema
|
|
203
|
+
}
|
|
204
|
+
}, {
|
|
205
|
+
name: "query",
|
|
206
|
+
wire: "query",
|
|
207
|
+
source: "json",
|
|
208
|
+
codec: {
|
|
209
|
+
mode: "strict",
|
|
210
|
+
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/search:query",
|
|
211
|
+
schema: searchQuery$schema
|
|
212
|
+
}
|
|
213
|
+
}],
|
|
214
|
+
cancellation: { parameter: "signal" },
|
|
215
|
+
result: {
|
|
216
|
+
mode: "strict",
|
|
217
|
+
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/search:result",
|
|
218
|
+
schema: searchResult$schema
|
|
219
|
+
}
|
|
173
220
|
}
|
|
174
221
|
]
|
|
175
222
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** One 16px icon family for document identity, tree rows and quick entries. */
|
|
2
|
+
export declare function DocumentIcon({ kind, expanded, className }: {
|
|
3
|
+
kind?: 'directory' | 'markdown' | 'image' | 'text' | 'file';
|
|
4
|
+
expanded?: boolean;
|
|
5
|
+
className?: string;
|
|
6
|
+
}): import("react").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=DocumentIcon.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** The panel relationship shared by the Session Header entry and its close control. */
|
|
2
|
+
export declare const PREVIEW_PANEL_ID = "dsh-md-preview-panel";
|
|
3
|
+
/** Distinct native glyphs for the document entry and close action, with localized next-action labels. */
|
|
4
|
+
export declare function PanelToggle({ open, label, onClick, entry }: {
|
|
5
|
+
open: boolean;
|
|
6
|
+
label: string;
|
|
7
|
+
onClick(): void;
|
|
8
|
+
entry?: boolean;
|
|
9
|
+
}): import("react").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=PanelToggle.d.ts.map
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
2
2
|
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
3
3
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
4
|
-
import type { MdPreviewFile, MdPreviewListResult, MdPreviewWriteResult } from '../protocol.ts';
|
|
4
|
+
import type { MdPreviewFile, MdPreviewListResult, MdPreviewSearchResult, MdPreviewWriteResult } from '../protocol.ts';
|
|
5
5
|
import type { MdPreviewState, MdPreviewTarget } from './preview-state.ts';
|
|
6
|
+
import type { LeaveIntentSeat } from './leave-intent.ts';
|
|
7
|
+
import type { ReadingStore } from './reading.ts';
|
|
8
|
+
import type { PanelPreferenceStore } from './preferences.ts';
|
|
6
9
|
/** Read/write/list RPCs and panel dismissal, created in the plugin's apply world. */
|
|
7
10
|
export interface PreviewOverlayInjected {
|
|
8
11
|
hooks: {
|
|
9
12
|
/** Current preview target; null while the panel is closed. */
|
|
10
13
|
previewTarget: SnapshotStore<MdPreviewState>;
|
|
11
14
|
};
|
|
15
|
+
/** The common leave-intent entry every plugin outlet shares (#21). */
|
|
16
|
+
leave: LeaveIntentSeat;
|
|
12
17
|
/** Dismiss the panel and drop the target. */
|
|
13
18
|
close(): void;
|
|
14
19
|
/** Set the preview target (the browser face's file-open handoff). */
|
|
@@ -19,13 +24,25 @@ export interface PreviewOverlayInjected {
|
|
|
19
24
|
write(sessionId: SessionId, path: string, content: string, fingerprint: string | undefined, force: boolean, signal: AbortSignal): Promise<import('@deepseek-ai/dsh-typert-protocol').RemoteResult<MdPreviewWriteResult>>;
|
|
20
25
|
/** One workspace directory listing; blank path lists the root. */
|
|
21
26
|
list(sessionId: SessionId, path: string, signal: AbortSignal): Promise<import('@deepseek-ai/dsh-typert-protocol').RemoteResult<MdPreviewListResult>>;
|
|
27
|
+
/** One workspace document search; the transport carries the AbortSignal. */
|
|
28
|
+
search(sessionId: SessionId, query: string, signal: AbortSignal): Promise<import('@deepseek-ai/dsh-typert-protocol').RemoteResult<MdPreviewSearchResult>>;
|
|
29
|
+
/** The reading record store (#25): per-(session, path) positions. */
|
|
30
|
+
reading: ReadingStore;
|
|
31
|
+
/** The current-turn outputs seat (#31): the session header's published
|
|
32
|
+
* view of the newest turn's produced documents. */
|
|
33
|
+
turnOutputs?: SnapshotStore<{
|
|
34
|
+
readonly sessionId: SessionId;
|
|
35
|
+
readonly paths: readonly string[];
|
|
36
|
+
} | null>;
|
|
37
|
+
/** The panel preference record (#26): manual geometry and navigation choices. */
|
|
38
|
+
preferences: PanelPreferenceStore;
|
|
22
39
|
}
|
|
23
40
|
/** Full composed panel props. */
|
|
24
41
|
export type PreviewOverlayProps = PropsRuntime<'shell.overlay'> & InjectFace<PreviewOverlayInjected> & PropsLocale<'md-preview'>;
|
|
25
42
|
/**
|
|
26
43
|
* Render the preview panel for the current target.
|
|
27
|
-
* @param props - target hook, read/write RPCs, dismissal, and the locale seat.
|
|
28
|
-
* @returns the docked panel
|
|
44
|
+
* @param props - target hook, leave seat, read/write RPCs, dismissal, and the locale seat.
|
|
45
|
+
* @returns the docked panel and its hidden shell anchor.
|
|
29
46
|
*/
|
|
30
|
-
export declare function PreviewOverlay({ usePreviewTarget, close, setTarget, read, write, list, t }: PreviewOverlayProps): import("react").JSX.Element
|
|
47
|
+
export declare function PreviewOverlay({ usePreviewTarget, useSessions, leave, close, setTarget, read, write, list, search, reading, turnOutputs, preferences, t }: PreviewOverlayProps): import("react").JSX.Element;
|
|
31
48
|
//# sourceMappingURL=PreviewOverlay.d.ts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
|
|
2
2
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
3
|
-
import type {
|
|
4
|
-
/** Listing RPC and the file-open handoff, created in the plugin's apply world. */
|
|
3
|
+
import type { MdPreviewListResult, MdPreviewSearchResult } from '../protocol.ts';
|
|
4
|
+
/** Listing RPC, the search RPC, and the file-open handoff, created in the plugin's apply world. */
|
|
5
5
|
export interface WorkspaceBrowserProps {
|
|
6
6
|
/** Owning session whose workspace the tree roots at. */
|
|
7
7
|
sessionId: SessionId;
|
|
@@ -9,28 +9,41 @@ export interface WorkspaceBrowserProps {
|
|
|
9
9
|
active: boolean;
|
|
10
10
|
/** One directory listing; the transport carries the AbortSignal. */
|
|
11
11
|
list(sessionId: SessionId, path: string, signal: AbortSignal): Promise<RemoteResult<MdPreviewListResult>>;
|
|
12
|
+
/** One workspace document search; the transport carries the AbortSignal. */
|
|
13
|
+
search(sessionId: SessionId, query: string, signal: AbortSignal): Promise<RemoteResult<MdPreviewSearchResult>>;
|
|
12
14
|
/** Open one file as the panel's preview target. */
|
|
13
15
|
onOpenFile(path: string): void;
|
|
16
|
+
/** Previewable documents the session's newest turn produced (#31); null
|
|
17
|
+
* while no owning-session facts were published, empty when it produced
|
|
18
|
+
* none — the section hides either way. */
|
|
19
|
+
turnOutputs?: readonly string[] | null;
|
|
20
|
+
/** The session's recently read documents, recency-first (#31). */
|
|
21
|
+
recentReads?: ReadonlyArray<{
|
|
22
|
+
readonly path: string;
|
|
23
|
+
}>;
|
|
14
24
|
/** Workspace-relative path of the current preview target, if any. */
|
|
15
25
|
currentPath: string | null;
|
|
26
|
+
/** Owning session's cwd, supplied by the platform selector, for display only. */
|
|
27
|
+
workspaceRoot?: string | undefined;
|
|
28
|
+
/** The session's continue-reading target, or null without a record (#28). */
|
|
29
|
+
continueTarget?: {
|
|
30
|
+
readonly path: string;
|
|
31
|
+
} | null;
|
|
32
|
+
/** Open the continue-reading target through the unified leave entry (#28). */
|
|
33
|
+
onContinue?: () => void;
|
|
16
34
|
/** Locale seat. */
|
|
17
35
|
t(key: string): string;
|
|
18
36
|
}
|
|
37
|
+
/** How long the search box waits for typing to settle before one RPC (#30). */
|
|
38
|
+
export declare const SEARCH_DEBOUNCE_MS = 200;
|
|
39
|
+
/** Quick entries stay few (#31): the caps each section shows. */
|
|
40
|
+
export declare const QUICK_TURN_MAX = 5;
|
|
41
|
+
export declare const QUICK_RECENT_MAX = 3;
|
|
19
42
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* @
|
|
24
|
-
* @param query - the raw filter text; blank shows everything.
|
|
25
|
-
* @param childrenOf - resolves a loaded directory's entries (undefined
|
|
26
|
-
* while unloaded or failed).
|
|
27
|
-
* @returns the entries this level should render.
|
|
43
|
+
* Render the workspace tree (and, while a query is live, the search results)
|
|
44
|
+
* for one session.
|
|
45
|
+
* @param props - session identity, listing/search RPCs, file-open handoff, locale seat.
|
|
46
|
+
* @returns the browse area's tree/search elements.
|
|
28
47
|
*/
|
|
29
|
-
export declare function
|
|
30
|
-
/**
|
|
31
|
-
* Render the workspace tree for one session.
|
|
32
|
-
* @param props - session identity, listing RPC, file-open handoff, locale seat.
|
|
33
|
-
* @returns the tree element.
|
|
34
|
-
*/
|
|
35
|
-
export declare function WorkspaceBrowser({ sessionId, active, list, onOpenFile, currentPath, t }: WorkspaceBrowserProps): import("react").JSX.Element;
|
|
48
|
+
export declare function WorkspaceBrowser({ sessionId, active, list, search, onOpenFile, turnOutputs, recentReads, currentPath, workspaceRoot, continueTarget, onContinue, t }: WorkspaceBrowserProps): import("react").JSX.Element;
|
|
36
49
|
//# sourceMappingURL=WorkspaceBrowser.d.ts.map
|
|
@@ -1,23 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* The document-sidebar toggle: a Session Header utility sitting next to
|
|
3
|
+
* the shipped Session-log download capsule. One entry with one meaning
|
|
4
|
+
* (#21): closed enters workspace browsing (the tree face), open requests the
|
|
5
|
+
* collapse — both through the common leave-intent entry, so a dirty draft is
|
|
6
|
+
* asked about before the panel folds. The panel owns docking and carries
|
|
7
|
+
* an X close control while the paperclip header entry stays mounted.
|
|
5
8
|
*/
|
|
6
|
-
import type
|
|
9
|
+
import { type ReactElement } from 'react';
|
|
10
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
7
11
|
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
8
12
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
13
|
+
import type { MdPreviewState } from './preview-state.ts';
|
|
14
|
+
import type { LeaveIntentSeat } from './leave-intent.ts';
|
|
15
|
+
import { type TurnOutputsSnapshot } from './turn-files.ts';
|
|
16
|
+
/** The composed props of the header utility: slot kit + inject face + locale. */
|
|
17
|
+
export type WorkspaceDocsActionProps = PropsRuntime<'conversation.session.header.utilities'> & InjectFace<{
|
|
18
|
+
hooks: {
|
|
19
|
+
previewTarget: SnapshotStore<MdPreviewState>;
|
|
20
|
+
};
|
|
21
|
+
leave: LeaveIntentSeat;
|
|
22
|
+
/** Publish the session's current-turn outputs into the shared seat (#31). */
|
|
23
|
+
publishTurnOutputs?(sessionId: SessionId, paths: readonly string[]): void;
|
|
24
|
+
}> & PropsLocale<'md-preview'> & {
|
|
25
|
+
/** The session binding's chat selector hook (ui-chat's standard source);
|
|
26
|
+
* absent when that plugin is not composed — nothing publishes then. */
|
|
27
|
+
useChat?: <T>(selector: (snapshot: TurnOutputsSnapshot) => T) => T;
|
|
28
|
+
};
|
|
17
29
|
/**
|
|
18
|
-
* Render the
|
|
30
|
+
* Render the document sidebar toggle for the showing Session.
|
|
19
31
|
* @param props - the composed action props.
|
|
20
|
-
* @returns the header button.
|
|
32
|
+
* @returns the header utility button.
|
|
21
33
|
*/
|
|
22
|
-
export declare function WorkspaceDocsAction(
|
|
34
|
+
export declare function WorkspaceDocsAction({ sessionId, usePreviewTarget, leave, publishTurnOutputs, useChat, t }: WorkspaceDocsActionProps): ReactElement;
|
|
23
35
|
//# sourceMappingURL=WorkspaceDocsAction.d.ts.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Display-only paths. Opening, saving and reading records keep the original identity. */
|
|
2
|
+
/** Remove the owning session's known workspace prefix, never an inferred root. */
|
|
3
|
+
export declare function workspaceDisplayPath(path: string, workspaceRoot?: string): string;
|
|
4
|
+
/** Parent context without repeating the document name on the second line. */
|
|
5
|
+
export declare function documentParent(path: string): string;
|
|
6
|
+
//# sourceMappingURL=document-path.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { MdPreviewTarget } from './preview-state.ts';
|
|
2
|
+
/** One requested way out of the current preview session. */
|
|
3
|
+
export type MdPreviewLeaveIntent = {
|
|
4
|
+
readonly kind: 'close';
|
|
5
|
+
} | {
|
|
6
|
+
readonly kind: 'switchFace';
|
|
7
|
+
} | {
|
|
8
|
+
readonly kind: 'open';
|
|
9
|
+
readonly target: MdPreviewTarget;
|
|
10
|
+
};
|
|
11
|
+
/** The leave-intent seat shared by every entry and the guarding panel. */
|
|
12
|
+
export interface LeaveIntentSeat {
|
|
13
|
+
/**
|
|
14
|
+
* Request one leave. Ignored while an earlier intent still waits behind
|
|
15
|
+
* the guard — the pending target cannot be silently replaced.
|
|
16
|
+
* @param intent - the requested close, face switch, or open.
|
|
17
|
+
*/
|
|
18
|
+
request(intent: MdPreviewLeaveIntent): void;
|
|
19
|
+
/** Drop the pending intent (「继续编辑」, or after execution). */
|
|
20
|
+
clear(): void;
|
|
21
|
+
/** Snapshot-store subscription face for the panel's binding. */
|
|
22
|
+
subscribe(listener: () => void): () => void;
|
|
23
|
+
/** The pending intent, or null while none waits. */
|
|
24
|
+
getSnapshot(): MdPreviewLeaveIntent | null;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Create the leave-intent seat for one plugin mount.
|
|
28
|
+
* @returns the seat to inject into the entries and the preview panel.
|
|
29
|
+
*/
|
|
30
|
+
export declare function createLeaveIntentSeat(): LeaveIntentSeat;
|
|
31
|
+
//# sourceMappingURL=leave-intent.d.ts.map
|
|
@@ -5,11 +5,15 @@ export declare const NS = "md-preview";
|
|
|
5
5
|
export declare const zh: {
|
|
6
6
|
'panel.title': string;
|
|
7
7
|
'panel.close': string;
|
|
8
|
+
'panel.maximize': string;
|
|
9
|
+
'panel.restore': string;
|
|
10
|
+
'panel.pickFile': string;
|
|
8
11
|
'panel.loading': string;
|
|
9
12
|
'panel.empty': string;
|
|
10
13
|
'panel.error': string;
|
|
11
14
|
'panel.unsupported': string;
|
|
12
15
|
'panel.retry': string;
|
|
16
|
+
'panel.failBrowse': string;
|
|
13
17
|
'panel.edit': string;
|
|
14
18
|
'panel.view': string;
|
|
15
19
|
'panel.face': string;
|
|
@@ -20,9 +24,12 @@ export declare const zh: {
|
|
|
20
24
|
'panel.redo': string;
|
|
21
25
|
'status.chars': string;
|
|
22
26
|
'status.saved': string;
|
|
27
|
+
'status.saving': string;
|
|
28
|
+
'status.saveFailed': string;
|
|
23
29
|
'status.unsaved': string;
|
|
24
30
|
'status.clean': string;
|
|
25
31
|
'panel.keys': string;
|
|
32
|
+
'panel.more': string;
|
|
26
33
|
'keys.bold': string;
|
|
27
34
|
'keys.italic': string;
|
|
28
35
|
'keys.link': string;
|
|
@@ -37,8 +44,10 @@ export declare const zh: {
|
|
|
37
44
|
'warn.dismiss': string;
|
|
38
45
|
'panel.saved': string;
|
|
39
46
|
'panel.saveError': string;
|
|
47
|
+
'panel.saved.readFailed': string;
|
|
40
48
|
'panel.save.retry': string;
|
|
41
49
|
'panel.conflict.title': string;
|
|
50
|
+
'panel.conflict.hint': string;
|
|
42
51
|
'panel.conflict.reload': string;
|
|
43
52
|
'panel.conflict.force': string;
|
|
44
53
|
'panel.unsaved.title': string;
|
|
@@ -51,11 +60,25 @@ export declare const zh: {
|
|
|
51
60
|
'browse.error': string;
|
|
52
61
|
'browse.retry': string;
|
|
53
62
|
'browse.refresh': string;
|
|
54
|
-
'browse.
|
|
55
|
-
'
|
|
63
|
+
'browse.search': string;
|
|
64
|
+
'search.label': string;
|
|
65
|
+
'search.clear': string;
|
|
66
|
+
'search.results': string;
|
|
67
|
+
'search.searching': string;
|
|
68
|
+
'search.none': string;
|
|
69
|
+
'search.failed': string;
|
|
70
|
+
'search.retry': string;
|
|
71
|
+
'search.incomplete': string;
|
|
72
|
+
'search.limit.directory-failure': string;
|
|
73
|
+
'search.limit.traversal-limit': string;
|
|
74
|
+
'search.limit.result-limit': string;
|
|
56
75
|
'rail.files': string;
|
|
57
76
|
'rail.outline': string;
|
|
58
77
|
'rail.noHeadings': string;
|
|
78
|
+
'continue.read': string;
|
|
79
|
+
'quick.turn': string;
|
|
80
|
+
'quick.recent': string;
|
|
81
|
+
'quick.open': string;
|
|
59
82
|
'outline.open': string;
|
|
60
83
|
'find.status': string;
|
|
61
84
|
'find.phrases.find': string;
|
|
@@ -73,6 +96,7 @@ export declare const zh: {
|
|
|
73
96
|
'chip.open': string;
|
|
74
97
|
'action.label': string;
|
|
75
98
|
'dock.browse': string;
|
|
99
|
+
'dock.expand': string;
|
|
76
100
|
'action.open': string;
|
|
77
101
|
copy: string;
|
|
78
102
|
copied: string;
|
|
@@ -17,6 +17,8 @@ export interface OutlineEntry {
|
|
|
17
17
|
* @returns ATX headings in order; fenced code is not scanned.
|
|
18
18
|
*/
|
|
19
19
|
export declare function extractOutline(content: string): readonly OutlineEntry[];
|
|
20
|
+
/** Whitespace-collapsed comparable form of a rendered heading's text. */
|
|
21
|
+
export declare function comparable(text: string): string;
|
|
20
22
|
/**
|
|
21
23
|
* Resolve the rendered DOM heading of one outline entry.
|
|
22
24
|
* @param container - the rendered document container.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Reversible layout adapter for the pinned shell.overlay DOM (ADR-0004). */
|
|
2
|
+
export interface PanelDockRequest {
|
|
3
|
+
readonly open: boolean;
|
|
4
|
+
readonly width: number;
|
|
5
|
+
readonly maximized: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface PanelDockBounds {
|
|
8
|
+
readonly left: number;
|
|
9
|
+
readonly top: number;
|
|
10
|
+
readonly height: number;
|
|
11
|
+
readonly width: number;
|
|
12
|
+
readonly reserved: number;
|
|
13
|
+
}
|
|
14
|
+
/** Resolve presentation geometry without changing the reader's width preference. */
|
|
15
|
+
export declare function panelDockGeometry(available: number, requested: number, open: boolean, maximized: boolean): {
|
|
16
|
+
width: number;
|
|
17
|
+
reserved: number;
|
|
18
|
+
};
|
|
19
|
+
/** Ownership handle: frame style, geometry observations, and scheduled work share one lifetime. */
|
|
20
|
+
export interface PanelDock {
|
|
21
|
+
/** Outside the clipping frame, inside the host root's inert/modal boundary. */
|
|
22
|
+
readonly container: HTMLElement;
|
|
23
|
+
update(request: PanelDockRequest): void;
|
|
24
|
+
dispose(): void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Locate only the frame enclosing our own shell contribution. No host DOM is
|
|
28
|
+
* moved and no feature store or slot occupant is replaced. An unknown mount
|
|
29
|
+
* keeps the original overlay presentation instead of guessing a frame.
|
|
30
|
+
*/
|
|
31
|
+
export declare function attachPanelDock(anchor: HTMLElement, report: (bounds: PanelDockBounds) => void): PanelDock | null;
|
|
32
|
+
//# sourceMappingURL=panel-dock.d.ts.map
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The panel preference record (#26): what lets the reader's own reading
|
|
3
|
+
* space survive closes and revisits. UI-local viewing preferences only —
|
|
4
|
+
* the dragged panel width, the rail width, the rail collapse choice, and
|
|
5
|
+
* the per-session files/outline choice; never file content, drafts, or
|
|
6
|
+
* session facts. The envelope is versioned, every loaded value validated,
|
|
7
|
+
* remembered sessions bounded, and every failing storage call degrades to
|
|
8
|
+
* the in-memory copy — a first open never lands on a bogus zero width.
|
|
9
|
+
*/
|
|
10
|
+
import type { StorageLike } from './reading.ts';
|
|
11
|
+
/** Envelope format version; an unknown version means an old, unreadable record. */
|
|
12
|
+
export declare const PANEL_PREFERENCE_VERSION = 1;
|
|
13
|
+
/** Panel width support range (the overlay's drag bounds). */
|
|
14
|
+
export declare const PANEL_MIN_WIDTH = 360;
|
|
15
|
+
export declare const PANEL_MAX_WIDTH = 1200;
|
|
16
|
+
export declare const PANEL_DEFAULT_WIDTH = 720;
|
|
17
|
+
/** Rail width support range (the rail's drag bounds). */
|
|
18
|
+
export declare const RAIL_MIN_WIDTH = 120;
|
|
19
|
+
export declare const RAIL_MAX_WIDTH = 320;
|
|
20
|
+
export declare const RAIL_DEFAULT_WIDTH = 220;
|
|
21
|
+
/** Which rail mini-tab the panel shows. */
|
|
22
|
+
export type RailTab = 'files' | 'outline';
|
|
23
|
+
/** The geometry facts a reader may have manually chosen (null = never chosen). */
|
|
24
|
+
export interface PanelGeometryPreferences {
|
|
25
|
+
readonly panelWidth: number | null;
|
|
26
|
+
readonly railWidth: number | null;
|
|
27
|
+
readonly railCollapsed: boolean | null;
|
|
28
|
+
}
|
|
29
|
+
/** The panel-facing preference store. */
|
|
30
|
+
export interface PanelPreferenceStore {
|
|
31
|
+
/** The remembered geometry (validated; nulls where nothing valid lives). */
|
|
32
|
+
geometry(): PanelGeometryPreferences;
|
|
33
|
+
/** Record one or more manual geometry choices (later values win per field). */
|
|
34
|
+
recordGeometry(partial: Partial<PanelGeometryPreferences>): void;
|
|
35
|
+
/** The remembered files/outline choice of one session, or null. */
|
|
36
|
+
railTab(sessionId: string): RailTab | null;
|
|
37
|
+
/** Record one session's files/outline choice. */
|
|
38
|
+
recordRailTab(sessionId: string, tab: RailTab): void;
|
|
39
|
+
}
|
|
40
|
+
/** An in-memory StorageLike for tests and for browsers without storage. */
|
|
41
|
+
export declare function createMemoryStorage(): StorageLike;
|
|
42
|
+
/** The browser's localStorage when reachable, else null (memory fallback). */
|
|
43
|
+
export declare function browserStorage(): StorageLike | null;
|
|
44
|
+
/**
|
|
45
|
+
* Create the panel preference store over one storage backend.
|
|
46
|
+
* @param storage - the persistence face; failing calls degrade to memory.
|
|
47
|
+
*/
|
|
48
|
+
export declare function createPanelPreferenceStore(storage: StorageLike): PanelPreferenceStore;
|
|
49
|
+
/**
|
|
50
|
+
* The width to open the panel at: the stored manual width when one exists,
|
|
51
|
+
* else the default preset — both clamped into the support range and the
|
|
52
|
+
* live viewport, so a shrunken screen never overflows and an absent value
|
|
53
|
+
* never lands on a bogus minimum.
|
|
54
|
+
* @param stored - the remembered manual width, or null when never chosen.
|
|
55
|
+
* @param viewportWidth - the live viewport width (0 = unknown).
|
|
56
|
+
*/
|
|
57
|
+
export declare function clampPanelWidth(stored: number | null, viewportWidth: number): number;
|
|
58
|
+
/**
|
|
59
|
+
* The rail width to open at (the same treatment on the rail's own range).
|
|
60
|
+
* @param stored - the remembered manual rail width, or null.
|
|
61
|
+
*/
|
|
62
|
+
export declare function clampRailWidth(stored: number | null): number;
|
|
63
|
+
//# sourceMappingURL=preferences.d.ts.map
|