@benz-ai-x/dsh-md-preview 0.1.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 +64 -0
- package/cordis.patch.yml +8 -0
- package/lib/client.js +5287 -0
- package/lib/index.js +210 -0
- package/lib/typert/remote-client.js +58 -0
- package/lib/types/client/MdChips.d.ts +28 -0
- package/lib/types/client/PreviewAction.d.ts +15 -0
- package/lib/types/client/PreviewOverlay.d.ts +26 -0
- package/lib/types/client/index.d.ts +13 -0
- package/lib/types/client/locale.d.ts +24 -0
- package/lib/types/client/message-files.d.ts +34 -0
- package/lib/types/client/mount.d.ts +19 -0
- package/lib/types/client/preview-state.d.ts +21 -0
- package/lib/types/client/styles.d.ts +9 -0
- package/lib/types/client/turn-files.d.ts +26 -0
- package/lib/types/config.d.ts +12 -0
- package/lib/types/constants.d.ts +6 -0
- package/lib/types/index.d.ts +24 -0
- package/lib/types/protocol.d.ts +41 -0
- package/lib/types/remote.d.ts +43 -0
- package/lib/types/typert/remote-client.d.ts +18 -0
- package/package.json +92 -0
package/lib/index.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { Remote, RemoteError, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
2
|
+
import z from "@deepseek-ai/schemastery";
|
|
3
|
+
//#region src/constants.ts
|
|
4
|
+
/** Schema-free deployment constants shared by Host config and browser face. */
|
|
5
|
+
/** Universal default: 1 MiB keeps a preview read bounded for any deployment. */
|
|
6
|
+
const DEFAULT_MAX_BYTES = 1048576;
|
|
7
|
+
/** Markdown documents are the previewable vocabulary; deployments may widen it. */
|
|
8
|
+
const DEFAULT_ALLOWED_EXTENSIONS = [".md", ".markdown"];
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/remote.ts
|
|
11
|
+
var __runInitializers = function(thisArg, initializers, value) {
|
|
12
|
+
var useValue = arguments.length > 2;
|
|
13
|
+
for (var i = 0; i < initializers.length; i++) value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
14
|
+
return useValue ? value : void 0;
|
|
15
|
+
};
|
|
16
|
+
var __esDecorate = function(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
17
|
+
function accept(f) {
|
|
18
|
+
if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected");
|
|
19
|
+
return f;
|
|
20
|
+
}
|
|
21
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
22
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
23
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
24
|
+
var _, done = false;
|
|
25
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
26
|
+
var context = {};
|
|
27
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
28
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
29
|
+
context.addInitializer = function(f) {
|
|
30
|
+
if (done) throw new TypeError("Cannot add initializers after decoration has completed");
|
|
31
|
+
extraInitializers.push(accept(f || null));
|
|
32
|
+
};
|
|
33
|
+
var result = (0, decorators[i])(kind === "accessor" ? {
|
|
34
|
+
get: descriptor.get,
|
|
35
|
+
set: descriptor.set
|
|
36
|
+
} : descriptor[key], context);
|
|
37
|
+
if (kind === "accessor") {
|
|
38
|
+
if (result === void 0) continue;
|
|
39
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
40
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
41
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
42
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
43
|
+
} else if (_ = accept(result)) {
|
|
44
|
+
if (kind === "field") initializers.unshift(_);
|
|
45
|
+
else descriptor[key] = _;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
49
|
+
done = true;
|
|
50
|
+
};
|
|
51
|
+
/** Business rejection with a stable code; the transport preserves it verbatim. */
|
|
52
|
+
function failure(code, message) {
|
|
53
|
+
return new RemoteError(code, message, {});
|
|
54
|
+
}
|
|
55
|
+
/** Lowercased dot-prefixed extension of a path, or the empty string. */
|
|
56
|
+
function extensionOf(path) {
|
|
57
|
+
const name = path.slice(Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")) + 1);
|
|
58
|
+
const dot = name.lastIndexOf(".");
|
|
59
|
+
return dot === -1 ? "" : name.slice(dot).toLowerCase();
|
|
60
|
+
}
|
|
61
|
+
/** Whether a candidate extension passes the configured allowlist. */
|
|
62
|
+
function isAllowedExtension(path, allowedExtensions) {
|
|
63
|
+
const extension = extensionOf(path);
|
|
64
|
+
return extension !== "" && allowedExtensions.includes(extension);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Host Remote service exposing `mdPreview/read` over the Gateway.
|
|
68
|
+
*/
|
|
69
|
+
let MdPreviewService = (() => {
|
|
70
|
+
let _classSuper = TypertRemoteService;
|
|
71
|
+
let _instanceExtraInitializers = [];
|
|
72
|
+
let _read_decorators;
|
|
73
|
+
return class MdPreviewService extends _classSuper {
|
|
74
|
+
static {
|
|
75
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
76
|
+
_read_decorators = [Remote];
|
|
77
|
+
__esDecorate(this, null, _read_decorators, {
|
|
78
|
+
kind: "method",
|
|
79
|
+
name: "read",
|
|
80
|
+
static: false,
|
|
81
|
+
private: false,
|
|
82
|
+
access: {
|
|
83
|
+
has: (obj) => "read" in obj,
|
|
84
|
+
get: (obj) => obj.read
|
|
85
|
+
},
|
|
86
|
+
metadata: _metadata
|
|
87
|
+
}, null, _instanceExtraInitializers);
|
|
88
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, {
|
|
89
|
+
enumerable: true,
|
|
90
|
+
configurable: true,
|
|
91
|
+
writable: true,
|
|
92
|
+
value: _metadata
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
static inject = [
|
|
96
|
+
"fs",
|
|
97
|
+
"typert",
|
|
98
|
+
"sessions"
|
|
99
|
+
];
|
|
100
|
+
/**
|
|
101
|
+
* Validated deployment configuration. TypeScript-private (not a `#` field):
|
|
102
|
+
* Cordis wraps plugin instances in proxies, and private fields fail their
|
|
103
|
+
* brand check through a proxy boundary.
|
|
104
|
+
*/
|
|
105
|
+
config = __runInitializers(this, _instanceExtraInitializers);
|
|
106
|
+
/**
|
|
107
|
+
* Bind the service to its Host context and validated configuration.
|
|
108
|
+
* @param ctx - Host context carrying fs, typert, and sessions services.
|
|
109
|
+
* @param config - Loader-validated deployment configuration.
|
|
110
|
+
*/
|
|
111
|
+
constructor(ctx, config) {
|
|
112
|
+
super(ctx, "mdPreview", { namespace: "mdPreview" });
|
|
113
|
+
this.config = config;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Read one previewable file from the session's workspace.
|
|
117
|
+
* @param sessionId - owning session; its header cwd roots the read.
|
|
118
|
+
* @param path - path as it appeared in the conversation.
|
|
119
|
+
* @param signal - caller cancellation carried through every fs call.
|
|
120
|
+
* @returns the path with its complete text content.
|
|
121
|
+
* @throws RemoteError with a stable MdPreview failure code.
|
|
122
|
+
*/
|
|
123
|
+
async read(sessionId, path, signal) {
|
|
124
|
+
if (path.trim().length === 0) throw failure("md-preview/bad-request", "mdPreview/read requires a non-empty path");
|
|
125
|
+
if (!isAllowedExtension(path, this.config.allowedExtensions)) throw failure("md-preview/unsupported-extension", `mdPreview/read refuses non-previewable path "${path}"`);
|
|
126
|
+
const session = this.ctx.sessions.get(sessionId);
|
|
127
|
+
if (session === void 0) throw failure("md-preview/unknown-session", `mdPreview/read cannot resolve session "${sessionId}"`);
|
|
128
|
+
const cwd = session.header.cwd;
|
|
129
|
+
if (cwd === void 0) throw failure("md-preview/no-workspace", `mdPreview/read session "${sessionId}" has no working directory`);
|
|
130
|
+
const root = await this.resolveWorkspacePath(cwd, signal);
|
|
131
|
+
let target;
|
|
132
|
+
try {
|
|
133
|
+
target = await this.resolveWorkspacePath(path, signal, cwd);
|
|
134
|
+
} catch (error) {
|
|
135
|
+
if (signal.aborted) throw error;
|
|
136
|
+
throw failure("md-preview/not-found", `mdPreview/read cannot resolve path "${path}"`);
|
|
137
|
+
}
|
|
138
|
+
if (!this.ctx.fs.contains(root, target)) throw failure("md-preview/forbidden", "mdPreview/read refuses paths outside the session workspace");
|
|
139
|
+
const info = await this.ctx.fs.stat(target, signal);
|
|
140
|
+
if (info === void 0) throw failure("md-preview/not-found", `mdPreview/read cannot find "${path}"`);
|
|
141
|
+
if (info.type !== "file") throw failure("md-preview/unsupported-extension", `mdPreview/read target "${path}" is not a regular file`);
|
|
142
|
+
if (info.size !== void 0 && info.size > this.config.maxBytes) throw failure("md-preview/too-large", `mdPreview/read refuses "${path}" above the configured byte cap`);
|
|
143
|
+
let content;
|
|
144
|
+
try {
|
|
145
|
+
content = await this.ctx.fs.readText(target, signal);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
if (signal.aborted) throw error;
|
|
148
|
+
throw failure("md-preview/unavailable", `mdPreview/read failed for "${path}": ${error instanceof Error ? error.message : String(error)}`);
|
|
149
|
+
}
|
|
150
|
+
if (content.length > this.config.maxBytes) throw failure("md-preview/too-large", `mdPreview/read refuses "${path}" above the configured byte cap`);
|
|
151
|
+
return {
|
|
152
|
+
path,
|
|
153
|
+
content
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/** Resolve one path against the workspace, with a plain not-found mapping. */
|
|
157
|
+
async resolveWorkspacePath(path, signal, cwd) {
|
|
158
|
+
return await this.ctx.fs.resolve(path, cwd === void 0 ? { signal } : {
|
|
159
|
+
cwd,
|
|
160
|
+
signal
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
})();
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region src/config.ts
|
|
167
|
+
/** Deployment configuration for the MdPreview Host service. */
|
|
168
|
+
/** Standard Schema twin of {@link Config}; defaults live here, not in code. */
|
|
169
|
+
const Config = z.object({
|
|
170
|
+
maxBytes: z.number().min(1).default(DEFAULT_MAX_BYTES),
|
|
171
|
+
allowedExtensions: z.array(z.string()).default([...DEFAULT_ALLOWED_EXTENSIONS])
|
|
172
|
+
});
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region src/protocol.ts
|
|
175
|
+
/** Stable failure codes carried by `RemoteError` across the wire. */
|
|
176
|
+
const MD_PREVIEW_FAILURE_CODES = [
|
|
177
|
+
"md-preview/bad-request",
|
|
178
|
+
"md-preview/unknown-session",
|
|
179
|
+
"md-preview/no-workspace",
|
|
180
|
+
"md-preview/unsupported-extension",
|
|
181
|
+
"md-preview/forbidden",
|
|
182
|
+
"md-preview/not-found",
|
|
183
|
+
"md-preview/too-large",
|
|
184
|
+
"md-preview/unavailable"
|
|
185
|
+
];
|
|
186
|
+
//#endregion
|
|
187
|
+
//#region src/index.ts
|
|
188
|
+
const name = "md-preview";
|
|
189
|
+
/** Host services the read authority depends on. */
|
|
190
|
+
const inject = [
|
|
191
|
+
"fs",
|
|
192
|
+
"typert",
|
|
193
|
+
"sessions"
|
|
194
|
+
];
|
|
195
|
+
/**
|
|
196
|
+
* Mount the MdPreview Host Remote.
|
|
197
|
+
* @param ctx - Host Loader context.
|
|
198
|
+
* @param config - Loader-validated deployment configuration (schema defaults
|
|
199
|
+
* fill any fields the profile patch omits).
|
|
200
|
+
*/
|
|
201
|
+
function apply(ctx, config = {
|
|
202
|
+
maxBytes: DEFAULT_MAX_BYTES,
|
|
203
|
+
allowedExtensions: [...DEFAULT_ALLOWED_EXTENSIONS]
|
|
204
|
+
}) {
|
|
205
|
+
ctx.plugin(MdPreviewService, config);
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
export { Config, DEFAULT_ALLOWED_EXTENSIONS, DEFAULT_MAX_BYTES, MD_PREVIEW_FAILURE_CODES, MdPreviewService, apply, inject, isAllowedExtension, name };
|
|
209
|
+
|
|
210
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
//#region src/typert/remote-client.ts
|
|
3
|
+
/**
|
|
4
|
+
* Browser-safe MdPreview Remote contribution.
|
|
5
|
+
*
|
|
6
|
+
* Hand-maintained twin of the artifacts `@deepseek-ai/dsh-typert-generator`
|
|
7
|
+
* emits for monorepo packages (see `packages/api/session-controller/lib/typert.remote-client.js`
|
|
8
|
+
* in the pinned Harness): one invocation descriptor plus zod strict codecs.
|
|
9
|
+
* The single `mdPreview/read` method takes its session identity as an
|
|
10
|
+
* explicit first business argument (the `goals/*` calling convention), so the
|
|
11
|
+
* browser face works from any client context, not only agent-scoped ones.
|
|
12
|
+
*/
|
|
13
|
+
const readSessionId$schema = z.string();
|
|
14
|
+
const readPath$schema = z.string().min(1);
|
|
15
|
+
const readResult$schema = z.object({
|
|
16
|
+
path: z.string(),
|
|
17
|
+
content: z.string()
|
|
18
|
+
});
|
|
19
|
+
/** The MdPreview contribution mounted by this package's browser entry. */
|
|
20
|
+
const TYPERT_REMOTE = {
|
|
21
|
+
package: "@benz-ai-x/dsh-md-preview",
|
|
22
|
+
descriptors: [{
|
|
23
|
+
id: "@benz-ai-x/dsh-md-preview#mdPreview/read",
|
|
24
|
+
service: "mdPreview",
|
|
25
|
+
namespace: "mdPreview",
|
|
26
|
+
method: "read",
|
|
27
|
+
invocation: { kind: "direct" },
|
|
28
|
+
parameters: [{
|
|
29
|
+
name: "sessionId",
|
|
30
|
+
wire: "sessionId",
|
|
31
|
+
source: "json",
|
|
32
|
+
codec: {
|
|
33
|
+
mode: "strict",
|
|
34
|
+
typeSymbol: "@deepseek-ai/dsh-session/types#SessionId",
|
|
35
|
+
schema: readSessionId$schema
|
|
36
|
+
}
|
|
37
|
+
}, {
|
|
38
|
+
name: "path",
|
|
39
|
+
wire: "path",
|
|
40
|
+
source: "json",
|
|
41
|
+
codec: {
|
|
42
|
+
mode: "strict",
|
|
43
|
+
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/read:path",
|
|
44
|
+
schema: readPath$schema
|
|
45
|
+
}
|
|
46
|
+
}],
|
|
47
|
+
cancellation: { parameter: "signal" },
|
|
48
|
+
result: {
|
|
49
|
+
mode: "strict",
|
|
50
|
+
typeSymbol: "@benz-ai-x/dsh-md-preview#mdPreview/read:result",
|
|
51
|
+
schema: readResult$schema
|
|
52
|
+
}
|
|
53
|
+
}]
|
|
54
|
+
};
|
|
55
|
+
//#endregion
|
|
56
|
+
export { TYPERT_REMOTE, TYPERT_REMOTE as default };
|
|
57
|
+
|
|
58
|
+
//# sourceMappingURL=remote-client.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The markdown-aware produced-files chip row, contributed into the
|
|
3
|
+
* `conversation.chat.turnTail` chain. This entry claims only turns that
|
|
4
|
+
* produced at least one markdown document and then renders the complete row:
|
|
5
|
+
* markdown chips open the in-browser preview panel, every other produced
|
|
6
|
+
* file keeps the shipped external-open behavior. Turns without markdown stay
|
|
7
|
+
* entirely with ui-deliverables' row.
|
|
8
|
+
*/
|
|
9
|
+
import type { InjectFace, PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
|
|
10
|
+
import type { TurnTailOwnerProps } from '@deepseek-ai/dsh-client-ui-chat/client';
|
|
11
|
+
import type { MdTurnFiles } from './turn-files.ts';
|
|
12
|
+
/** Panel admission for one conversation session. */
|
|
13
|
+
export interface MdChipsInjected {
|
|
14
|
+
/** Open the preview panel for a markdown document of this session. */
|
|
15
|
+
openPreview(path: string): void;
|
|
16
|
+
}
|
|
17
|
+
/** Matched paths plus the shipped file opener and the locale seat. */
|
|
18
|
+
export type MdChipsProps = Pick<TurnTailOwnerProps, 'openFile'> & {
|
|
19
|
+
matched: MdTurnFiles;
|
|
20
|
+
} & PropsLocale<'md-preview'> & InjectFace<MdChipsInjected>;
|
|
21
|
+
/**
|
|
22
|
+
* Render one turn's produced files as chips; markdown opens the preview.
|
|
23
|
+
* @param props - selector-matched paths, the chat view's file opener, preview
|
|
24
|
+
* admission, and the locale seat.
|
|
25
|
+
* @returns the produced-files chip row.
|
|
26
|
+
*/
|
|
27
|
+
export declare function MdChips({ matched, openFile, openPreview, t }: MdChipsProps): import("react").JSX.Element | null;
|
|
28
|
+
//# sourceMappingURL=MdChips.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
+
/** Panel admission for one conversation session. */
|
|
3
|
+
export interface PreviewActionInjected {
|
|
4
|
+
/** Open the preview panel for a markdown document of this session. */
|
|
5
|
+
openPreview(path: string): void;
|
|
6
|
+
}
|
|
7
|
+
/** Full composed action props: the owner message id plus the locale seat. */
|
|
8
|
+
export type PreviewActionProps = PropsRuntime<'conversation.chat.assistant-actions'> & PropsLocale<'md-preview'> & InjectFace<PreviewActionInjected>;
|
|
9
|
+
/**
|
|
10
|
+
* Render the preview-documents action for one finalized assistant message.
|
|
11
|
+
* @param props - the durable message id, preview admission, and locale seat.
|
|
12
|
+
* @returns the action button with its picker, or null without markdown.
|
|
13
|
+
*/
|
|
14
|
+
export declare function PreviewAction({ messageId, useChat, openPreview, t }: PreviewActionProps): import("react").JSX.Element | null;
|
|
15
|
+
//# sourceMappingURL=PreviewAction.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
2
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
3
|
+
import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
|
|
4
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
5
|
+
import type { MdPreviewFile } from '../protocol.ts';
|
|
6
|
+
import type { MdPreviewState } from './preview-state.ts';
|
|
7
|
+
/** Read RPC and panel dismissal, created in the plugin's apply world. */
|
|
8
|
+
export interface PreviewOverlayInjected {
|
|
9
|
+
hooks: {
|
|
10
|
+
/** Current preview target; null while the panel is closed. */
|
|
11
|
+
previewTarget: SnapshotStore<MdPreviewState>;
|
|
12
|
+
};
|
|
13
|
+
/** Dismiss the panel and drop the target. */
|
|
14
|
+
close(): void;
|
|
15
|
+
/** One bounded read; the transport carries the AbortSignal. */
|
|
16
|
+
read(sessionId: SessionId, path: string, signal: AbortSignal): Promise<RemoteResult<MdPreviewFile>>;
|
|
17
|
+
}
|
|
18
|
+
/** Full composed panel props. */
|
|
19
|
+
export type PreviewOverlayProps = PropsRuntime<'shell.overlay'> & InjectFace<PreviewOverlayInjected> & PropsLocale<'md-preview'>;
|
|
20
|
+
/**
|
|
21
|
+
* Render the preview panel for the current target.
|
|
22
|
+
* @param props - target hook, read RPC, dismissal, and the locale seat.
|
|
23
|
+
* @returns the docked panel, or null while closed.
|
|
24
|
+
*/
|
|
25
|
+
export declare function PreviewOverlay({ usePreviewTarget, close, read, t }: PreviewOverlayProps): import("react").JSX.Element | null;
|
|
26
|
+
//# sourceMappingURL=PreviewOverlay.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Browser entry binding the MdPreview Remote artifact to its Client UI. */
|
|
2
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
3
|
+
export { inject } from './mount.ts';
|
|
4
|
+
export type { MdChipsInjected } from './MdChips.tsx';
|
|
5
|
+
export type { PreviewActionInjected } from './PreviewAction.tsx';
|
|
6
|
+
export type { PreviewOverlayInjected } from './PreviewOverlay.tsx';
|
|
7
|
+
/**
|
|
8
|
+
* Mount the MdPreview Remote contribution and its browser UI.
|
|
9
|
+
* @param ctx - client root context.
|
|
10
|
+
* @returns disposer removing the namespace and every UI registration.
|
|
11
|
+
*/
|
|
12
|
+
export declare function apply(ctx: ClientContext): Promise<() => Promise<void>>;
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** `md-preview` namespace dictionaries. */
|
|
2
|
+
/** Dictionary namespace owned by this plugin. */
|
|
3
|
+
export declare const NS = "md-preview";
|
|
4
|
+
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
5
|
+
export declare const zh: {
|
|
6
|
+
'panel.title': string;
|
|
7
|
+
'panel.close': string;
|
|
8
|
+
'panel.loading': string;
|
|
9
|
+
'panel.empty': string;
|
|
10
|
+
'panel.error': string;
|
|
11
|
+
'panel.retry': string;
|
|
12
|
+
'chip.preview': string;
|
|
13
|
+
'chip.open': string;
|
|
14
|
+
'action.label': string;
|
|
15
|
+
'action.open': string;
|
|
16
|
+
copy: string;
|
|
17
|
+
copied: string;
|
|
18
|
+
footnotes: string;
|
|
19
|
+
};
|
|
20
|
+
/** English dictionary (same key set). */
|
|
21
|
+
export declare const en: Record<MdPreviewKey, string>;
|
|
22
|
+
/** Union of this namespace's dictionary keys. */
|
|
23
|
+
export type MdPreviewKey = keyof typeof zh;
|
|
24
|
+
//# sourceMappingURL=locale.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message-id to produced-markdown lookup over the Chat snapshot. Pure and
|
|
3
|
+
* bounded by the loaded window: the per-message preview action finds the
|
|
4
|
+
* turn-tail node whose closing assistant message owns the id and reads the
|
|
5
|
+
* same `deliverables` Turn data the chip row uses. The returned references
|
|
6
|
+
* ride the snapshot's structural sharing, so selectors stay identity-stable
|
|
7
|
+
* across unrelated publications.
|
|
8
|
+
*/
|
|
9
|
+
import type { ChatSnapshot } from '@deepseek-ai/dsh-client-ui-chat/client';
|
|
10
|
+
/** Deliverables Turn data plus the closing seq that fences it. */
|
|
11
|
+
export interface OwnedDeliverables {
|
|
12
|
+
/** Raw `deliverables` Turn data reference (structurally shared). */
|
|
13
|
+
readonly produced: readonly {
|
|
14
|
+
readonly seq: number;
|
|
15
|
+
readonly path: string;
|
|
16
|
+
}[];
|
|
17
|
+
/** Closing assistant seq; later settlements are excluded downstream. */
|
|
18
|
+
readonly seq: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Find the deliverables data of the turn whose closing message owns an id.
|
|
22
|
+
* @param snapshot - current Chat target snapshot (loaded window only).
|
|
23
|
+
* @param messageId - durable assistant message id from the action row.
|
|
24
|
+
* @returns the turn's produced entries and closing seq, or undefined outside
|
|
25
|
+
* the window or when the turn produced nothing.
|
|
26
|
+
*/
|
|
27
|
+
export declare function ownedDeliverables(snapshot: ChatSnapshot, messageId: string): OwnedDeliverables | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Previewable markdown documents of one turn, first-seen order, seq-cutoff applied.
|
|
30
|
+
* @param owned - deliverables data and closing seq of one turn.
|
|
31
|
+
* @returns previewable paths in first-seen order.
|
|
32
|
+
*/
|
|
33
|
+
export declare function previewableOf(owned: OwnedDeliverables): readonly string[];
|
|
34
|
+
//# sourceMappingURL=message-files.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Source-safe MdPreview browser registration and Remote mount lifecycle. */
|
|
2
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
3
|
+
import type { TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol';
|
|
4
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
5
|
+
interface LocaleNamespaceMap {
|
|
6
|
+
/** MdPreview panel, chips, and action copy. */
|
|
7
|
+
'md-preview': import('./locale.ts').MdPreviewKey;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Required browser services for the Remote mount, slots, and locale. */
|
|
11
|
+
export declare const inject: string[];
|
|
12
|
+
/**
|
|
13
|
+
* Mount the MdPreview Remote contribution, then register its browser UI.
|
|
14
|
+
* @param ctx - client root context carrying the Remote table, slots, and locale.
|
|
15
|
+
* @param contribution - this package's Remote descriptors.
|
|
16
|
+
* @returns disposer for both the UI registrations and the Remote namespace.
|
|
17
|
+
*/
|
|
18
|
+
export declare function mountMdPreview(ctx: ClientContext, contribution: TypertRemoteContribution): Promise<() => Promise<void>>;
|
|
19
|
+
//# sourceMappingURL=mount.d.ts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Preview target state shared by the conversation entries and the panel. */
|
|
2
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
3
|
+
/** The document the preview panel currently shows; null while closed. */
|
|
4
|
+
export interface MdPreviewTarget {
|
|
5
|
+
readonly sessionId: SessionId;
|
|
6
|
+
readonly path: string;
|
|
7
|
+
}
|
|
8
|
+
/** Whole preview panel state: the current target or the closed state. */
|
|
9
|
+
export type MdPreviewState = MdPreviewTarget | null;
|
|
10
|
+
/** Create the plugin-owned preview target store. */
|
|
11
|
+
export declare function createPreviewStore(): import("@deepseek-ai/dsh-client-store").SnapshotStore<MdPreviewState>;
|
|
12
|
+
/** Trailing path segment; the part that identifies a file at a glance. */
|
|
13
|
+
export declare function basename(path: string): string;
|
|
14
|
+
/** Whether the client treats a produced path as a previewable markdown document. */
|
|
15
|
+
export declare function isPreviewable(path: string): boolean;
|
|
16
|
+
/** Produced paths of one turn split into previewable and externally-opened groups, first-seen order preserved. */
|
|
17
|
+
export declare function splitPreviewable(paths: readonly string[]): {
|
|
18
|
+
previewable: string[];
|
|
19
|
+
other: string[];
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=preview-state.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Panel and chip styles. The DSH client shell claims `<style>` tags a plugin
|
|
3
|
+
* injects during materialization (tagged with data-plugin), so a plain
|
|
4
|
+
* one-time injection is lifecycle-correct without a CSS-modules pipeline.
|
|
5
|
+
* Colors ride the shared dsw alias tokens so light/dark themes both hold.
|
|
6
|
+
*/
|
|
7
|
+
/** Inject the plugin stylesheet once per browser document. */
|
|
8
|
+
export declare function ensureStyles(): void;
|
|
9
|
+
//# sourceMappingURL=styles.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn-scoped produced-file readers for the browser half. Client-only and
|
|
3
|
+
* deliverables-free at runtime: the vocabulary comes from the `deliverables`
|
|
4
|
+
* Conversation Turn data published by ui-deliverables (absent when that
|
|
5
|
+
* plugin is not composed — the selector declines and no chips render).
|
|
6
|
+
*/
|
|
7
|
+
import type { TurnTailOwnerProps } from '@deepseek-ai/dsh-client-ui-chat/client';
|
|
8
|
+
import type { TurnLocation } from '@deepseek-ai/dsh-client-ui-conversation/client';
|
|
9
|
+
/** Produced paths of one closing Turn, first-seen order, seq-cutoff applied. */
|
|
10
|
+
export declare function producedPaths(turn: TurnLocation, seq: number): readonly string[];
|
|
11
|
+
/** Matched value for the turn-tail chain entry. */
|
|
12
|
+
export interface MdTurnFiles {
|
|
13
|
+
/** Markdown documents this turn produced (open the preview panel). */
|
|
14
|
+
readonly previewable: readonly string[];
|
|
15
|
+
/** Every other produced file (keeps the shipped external-open behavior). */
|
|
16
|
+
readonly other: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Claim the turn-tail chain only for turns that produced at least one
|
|
20
|
+
* previewable markdown document. Claimed turns render this plugin's chip row
|
|
21
|
+
* (a superset of the shipped one); all other turns stay with ui-deliverables.
|
|
22
|
+
* @param owner - turn-tail owner currency for the closing assistant message.
|
|
23
|
+
* @returns the split paths when the turn produced markdown, otherwise null.
|
|
24
|
+
*/
|
|
25
|
+
export declare function selectMdTurnFiles(owner: TurnTailOwnerProps): MdTurnFiles | null;
|
|
26
|
+
//# sourceMappingURL=turn-files.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Deployment configuration for the MdPreview Host service. */
|
|
2
|
+
import z from '@deepseek-ai/schemastery';
|
|
3
|
+
/** Runtime-validated MdPreview configuration. */
|
|
4
|
+
export interface Config {
|
|
5
|
+
/** Largest file size the service will read and return, in bytes. */
|
|
6
|
+
maxBytes: number;
|
|
7
|
+
/** Extensions (lowercased, dot-prefixed) eligible for preview. */
|
|
8
|
+
allowedExtensions: string[];
|
|
9
|
+
}
|
|
10
|
+
/** Standard Schema twin of {@link Config}; defaults live here, not in code. */
|
|
11
|
+
export declare const Config: z<Config>;
|
|
12
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Schema-free deployment constants shared by Host config and browser face. */
|
|
2
|
+
/** Universal default: 1 MiB keeps a preview read bounded for any deployment. */
|
|
3
|
+
export declare const DEFAULT_MAX_BYTES = 1048576;
|
|
4
|
+
/** Markdown documents are the previewable vocabulary; deployments may widen it. */
|
|
5
|
+
export declare const DEFAULT_ALLOWED_EXTENSIONS: readonly [".md", ".markdown"];
|
|
6
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-md-preview Host entry: registers the MdPreview Remote service. The
|
|
3
|
+
* browser half lives at `./client` (see `dsh.client` in package.json); this
|
|
4
|
+
* module only owns the Host-side read authority.
|
|
5
|
+
*/
|
|
6
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
7
|
+
import { type Config as ConfigType } from './config.ts';
|
|
8
|
+
export { Config } from './config.ts';
|
|
9
|
+
export type { Config as ConfigInterface } from './config.ts';
|
|
10
|
+
export { DEFAULT_ALLOWED_EXTENSIONS, DEFAULT_MAX_BYTES } from './constants.ts';
|
|
11
|
+
export { isAllowedExtension, MdPreviewService } from './remote.ts';
|
|
12
|
+
export type { MdPreviewFile, MdPreviewFailureCode, MdPreviewReadRequest } from './protocol.ts';
|
|
13
|
+
export { MD_PREVIEW_FAILURE_CODES } from './protocol.ts';
|
|
14
|
+
export declare const name = "md-preview";
|
|
15
|
+
/** Host services the read authority depends on. */
|
|
16
|
+
export declare const inject: string[];
|
|
17
|
+
/**
|
|
18
|
+
* Mount the MdPreview Host Remote.
|
|
19
|
+
* @param ctx - Host Loader context.
|
|
20
|
+
* @param config - Loader-validated deployment configuration (schema defaults
|
|
21
|
+
* fill any fields the profile patch omits).
|
|
22
|
+
*/
|
|
23
|
+
export declare function apply(ctx: Context, config?: ConfigType): void;
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Wire-level vocabulary shared by the Host service and the browser face. */
|
|
2
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
3
|
+
/** One rendered-preview payload: the requested path and its full text content. */
|
|
4
|
+
export interface MdPreviewFile {
|
|
5
|
+
/** The path exactly as requested by the caller (tool-produced spelling). */
|
|
6
|
+
readonly path: string;
|
|
7
|
+
/** The complete file content, capped by the configured byte limit. */
|
|
8
|
+
readonly content: string;
|
|
9
|
+
}
|
|
10
|
+
/** Stable failure codes carried by `RemoteError` across the wire. */
|
|
11
|
+
export declare const MD_PREVIEW_FAILURE_CODES: readonly ["md-preview/bad-request", "md-preview/unknown-session", "md-preview/no-workspace", "md-preview/unsupported-extension", "md-preview/forbidden", "md-preview/not-found", "md-preview/too-large", "md-preview/unavailable"];
|
|
12
|
+
/** One stable MdPreview failure code. */
|
|
13
|
+
export type MdPreviewFailureCode = (typeof MD_PREVIEW_FAILURE_CODES)[number];
|
|
14
|
+
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
15
|
+
interface RemoteErrorDetailsMap {
|
|
16
|
+
/** The request path was empty or otherwise unusable. */
|
|
17
|
+
'md-preview/bad-request': {};
|
|
18
|
+
/** The named Session does not exist. */
|
|
19
|
+
'md-preview/unknown-session': {};
|
|
20
|
+
/** The Session carries no working directory to root the read. */
|
|
21
|
+
'md-preview/no-workspace': {};
|
|
22
|
+
/** The target is not a previewable markdown document. */
|
|
23
|
+
'md-preview/unsupported-extension': {};
|
|
24
|
+
/** The resolved path escapes the session workspace. */
|
|
25
|
+
'md-preview/forbidden': {};
|
|
26
|
+
/** Nothing exists at the requested path. */
|
|
27
|
+
'md-preview/not-found': {};
|
|
28
|
+
/** The file exceeds the configured byte cap. */
|
|
29
|
+
'md-preview/too-large': {};
|
|
30
|
+
/** The read itself failed. */
|
|
31
|
+
'md-preview/unavailable': {};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Read request shape as the browser face types it (wire fields stay flat). */
|
|
35
|
+
export interface MdPreviewReadRequest {
|
|
36
|
+
/** Owning session whose workspace roots the read. */
|
|
37
|
+
readonly sessionId: SessionId;
|
|
38
|
+
/** Path as it appeared in the conversation (absolute or workspace-relative). */
|
|
39
|
+
readonly path: string;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MdPreview Host Remote: reads one markdown document from a session's
|
|
3
|
+
* workspace for in-browser rendering. The read is deliberately scoped: the
|
|
4
|
+
* path must resolve inside the owning session's working directory, carry an
|
|
5
|
+
* allowed extension, and stay under the configured byte cap.
|
|
6
|
+
*/
|
|
7
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
8
|
+
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
9
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
10
|
+
import type { Config } from './config.ts';
|
|
11
|
+
import type { MdPreviewFile } from './protocol.ts';
|
|
12
|
+
/** Whether a candidate extension passes the configured allowlist. */
|
|
13
|
+
export declare function isAllowedExtension(path: string, allowedExtensions: readonly string[]): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Host Remote service exposing `mdPreview/read` over the Gateway.
|
|
16
|
+
*/
|
|
17
|
+
export declare class MdPreviewService extends TypertRemoteService {
|
|
18
|
+
static inject: string[];
|
|
19
|
+
/**
|
|
20
|
+
* Validated deployment configuration. TypeScript-private (not a `#` field):
|
|
21
|
+
* Cordis wraps plugin instances in proxies, and private fields fail their
|
|
22
|
+
* brand check through a proxy boundary.
|
|
23
|
+
*/
|
|
24
|
+
private readonly config;
|
|
25
|
+
/**
|
|
26
|
+
* Bind the service to its Host context and validated configuration.
|
|
27
|
+
* @param ctx - Host context carrying fs, typert, and sessions services.
|
|
28
|
+
* @param config - Loader-validated deployment configuration.
|
|
29
|
+
*/
|
|
30
|
+
constructor(ctx: Context, config: Config);
|
|
31
|
+
/**
|
|
32
|
+
* Read one previewable file from the session's workspace.
|
|
33
|
+
* @param sessionId - owning session; its header cwd roots the read.
|
|
34
|
+
* @param path - path as it appeared in the conversation.
|
|
35
|
+
* @param signal - caller cancellation carried through every fs call.
|
|
36
|
+
* @returns the path with its complete text content.
|
|
37
|
+
* @throws RemoteError with a stable MdPreview failure code.
|
|
38
|
+
*/
|
|
39
|
+
read(sessionId: SessionId, path: string, signal: AbortSignal): Promise<MdPreviewFile>;
|
|
40
|
+
/** Resolve one path against the workspace, with a plain not-found mapping. */
|
|
41
|
+
private resolveWorkspacePath;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=remote.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { RemoteResult, TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol';
|
|
2
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
3
|
+
import type { MdPreviewFile } from '../protocol.ts';
|
|
4
|
+
/** Browser face of the mounted `mdPreview` Remote namespace. */
|
|
5
|
+
export interface MdPreviewRemote {
|
|
6
|
+
/** Read one previewable document of a session's workspace. */
|
|
7
|
+
read(sessionId: SessionId, path: string, signal?: AbortSignal): Promise<RemoteResult<MdPreviewFile>>;
|
|
8
|
+
}
|
|
9
|
+
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
10
|
+
interface TypertRemoteNamespaceMap {
|
|
11
|
+
/** Markdown preview reads over the Gateway. */
|
|
12
|
+
mdPreview: MdPreviewRemote;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** The MdPreview contribution mounted by this package's browser entry. */
|
|
16
|
+
export declare const TYPERT_REMOTE: TypertRemoteContribution;
|
|
17
|
+
export default TYPERT_REMOTE;
|
|
18
|
+
//# sourceMappingURL=remote-client.d.ts.map
|