dsh-image-gen 0.10.0 → 0.10.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.
@@ -0,0 +1,101 @@
1
+ import type { Editor } from 'tldraw';
2
+ import type { ImageAttachmentRef } from '@deepseek-ai/dsh-attachment';
3
+ interface TraceStep {
4
+ layer: number;
5
+ d: string;
6
+ area: number;
7
+ }
8
+ interface TracePlan {
9
+ viewBox: [number, number, number, number];
10
+ fills: string[];
11
+ steps: TraceStep[];
12
+ }
13
+ export interface CanvasTraceProps {
14
+ editor: Editor;
15
+ traceId: string;
16
+ /** Region count reported by the tool, shown before the plan arrives. */
17
+ steps: number;
18
+ /**
19
+ * The absolutely-positioned host the surface is rendered into. Its rect is
20
+ * the origin this component must subtract from tldraw's window-relative
21
+ * screen coordinates.
22
+ */
23
+ hostRef?: {
24
+ readonly current: HTMLDivElement | null;
25
+ };
26
+ /**
27
+ * Receives the finished drawing as a rail image plus the page rectangle it
28
+ * was drawn in, so the canvas can place it exactly where the playback was.
29
+ */
30
+ onLand?: ((attachment: ImageAttachmentRef, placement: {
31
+ x: number;
32
+ y: number;
33
+ w: number;
34
+ h: number;
35
+ }) => void | Promise<void>) | undefined;
36
+ onClose: () => void;
37
+ lang?: 'zh' | 'en';
38
+ }
39
+ /**
40
+ * Revealed region count at elapsed time `t`. Squaring the normalised time
41
+ * gives the first (largest) regions most of the screen time and then speeds up
42
+ * through the tiny ones, which is the same curve the drawai workbench uses.
43
+ */
44
+ export declare function traceRevealCount(total: number, elapsedMs: number, durationMs: number): number;
45
+ /** Total playback time for a plan: short plans stay readable, long ones stay bounded. */
46
+ export declare function tracePlaybackDuration(total: number): number;
47
+ /** Paint order prefix: the first `count` steps accumulated per colour layer. */
48
+ export declare function traceLayerPaths(plan: TracePlan, count: number): string[];
49
+ /** Rebuild the finished SVG document from the plan, for download. */
50
+ export declare function tracePlanToSvg(plan: TracePlan): string;
51
+ /**
52
+ * Draw the finished SVG into a canvas and encode it as PNG.
53
+ *
54
+ * SVG reaches the document as a bitmap because tldraw's image shapes render
55
+ * through `<img>`, where an SVG with only a viewBox has no intrinsic size and
56
+ * collapses to the 300x150 default. Width and height are injected for the same
57
+ * reason: without them the browser has nothing to scale from.
58
+ */
59
+ export declare function rasterizeSvg(svg: string, width: number, height: number): Promise<Blob>;
60
+ /** Upload rasterised bytes as a durable attachment so the canvas can land them. */
61
+ export declare function uploadDrawing(blob: Blob, name: string): Promise<ImageAttachmentRef>;
62
+ /** Rasterise one plan at a bounded resolution, then store it as an attachment. */
63
+ export declare function realizeDrawing(plan: TracePlan, name: string): Promise<ImageAttachmentRef>;
64
+ /** Page-space rectangle the drawing occupies, frozen when the trace starts. */
65
+ export interface TraceAnchor {
66
+ x: number;
67
+ y: number;
68
+ w: number;
69
+ h: number;
70
+ }
71
+ /**
72
+ * Pick the page rectangle for a drawing of `aspect` (w/h): centred on what the
73
+ * user is looking at right now, at 72% of the viewport. Frozen in page space so
74
+ * later panning and zooming move it like canvas content instead of resizing it
75
+ * to the window.
76
+ */
77
+ export declare function anchorTraceInViewport(viewport: {
78
+ center: {
79
+ x: number;
80
+ y: number;
81
+ };
82
+ w: number;
83
+ h: number;
84
+ }, aspect: number): TraceAnchor;
85
+ export declare function CanvasTrace({ editor, traceId, steps, hostRef, onLand, onClose, lang }: CanvasTraceProps): import("react").JSX.Element;
86
+ /**
87
+ * Map a page rectangle into the surface's own coordinate space.
88
+ *
89
+ * tldraw's screen space is window-relative (`pageToScreen` returns client
90
+ * coordinates, which is why collaborator cursors need no offset), while the
91
+ * surface is an absolutely positioned child of the canvas host. Subtracting the
92
+ * host's own rect is what turns one into the other; without it the drawing is
93
+ * pushed off the panel and clipped.
94
+ */
95
+ export declare function projectAnchor(editor: Editor, anchor: TraceAnchor, host: HTMLElement | null): {
96
+ left: number;
97
+ top: number;
98
+ width: number;
99
+ height: number;
100
+ };
101
+ export {};
@@ -1,3 +1,3 @@
1
1
  /** Live, credential-free instructions for the conversation model's image tools. */
2
2
  import { type Config } from './config.js';
3
- export declare function imageToolContext(config: Config): string;
3
+ export declare function imageToolContext(config: Config, configuredProviders?: readonly string[]): string;
@@ -1,5 +1,6 @@
1
1
  import type { Context } from '@deepseek-ai/cordis';
2
2
  import { SubscriptionManager } from './manager.js';
3
+ import { type WebAdmission } from '../web-route.js';
3
4
  export { SUBSCRIPTION_LOGIN_ROUTE, SUBSCRIPTION_STATUS_ROUTE } from '../shared.js';
4
5
  /** Register the login/status routes on the plugin's web server. */
5
- export declare function registerSubscriptionRoutes(ctx: Context, manager: SubscriptionManager): void;
6
+ export declare function registerSubscriptionRoutes(ctx: Context, manager: SubscriptionManager, admission?: () => WebAdmission | undefined): void;
@@ -0,0 +1,102 @@
1
+ /** Named trace styles exposed by the tool. */
2
+ export declare const TRACE_PRESET_NAMES: readonly ["default", "lineart", "photo", "simple"];
3
+ export type TracePresetName = (typeof TRACE_PRESET_NAMES)[number];
4
+ /** Fragment density tiers, mirroring the workbench's three calibrated档. */
5
+ export declare const TRACE_FRAGMENT_NAMES: readonly ["low", "medium", "high"];
6
+ export type TraceFragments = (typeof TRACE_FRAGMENT_NAMES)[number];
7
+ /** One connected region of one colour: a self-contained path plus its area. */
8
+ export interface TraceDrawingStep {
9
+ /** Index into `fills`; steps sharing a layer share a fill colour. */
10
+ layer: number;
11
+ /** SVG path data for this region, including its holes (nonzero winding). */
12
+ d: string;
13
+ /** Signed pixel area used for ordering; steps arrive largest first. */
14
+ area: number;
15
+ }
16
+ /** The replayable drawing: paint `steps` in order, grouped by `fills`. */
17
+ export interface TraceDrawingPlan {
18
+ viewBox: [number, number, number, number];
19
+ fills: string[];
20
+ steps: TraceDrawingStep[];
21
+ }
22
+ /** Numbers the model gets instead of the path data. */
23
+ export interface TraceSummary {
24
+ width: number;
25
+ height: number;
26
+ colors: number;
27
+ paths: number;
28
+ loops: number;
29
+ steps: number;
30
+ svgChars: number;
31
+ budget: number;
32
+ attempts: number;
33
+ drawnPixels: number | null;
34
+ exactPixelCoverage: boolean;
35
+ sourceWidth: number;
36
+ sourceHeight: number;
37
+ }
38
+ /** Everything one trace produces. */
39
+ export interface TraceOutcome {
40
+ /** Full SVG document, for export — never sent to the model verbatim. */
41
+ svg: string;
42
+ plan: TraceDrawingPlan;
43
+ /**
44
+ * Optional pencil pass derived from the same source, played before `plan`.
45
+ * Null when the caller asked for no sketch or the edge pass found nothing.
46
+ */
47
+ sketch: TraceDrawingPlan | null;
48
+ summary: TraceSummary;
49
+ /** One-line tuning advice from upstream's own heuristics. */
50
+ hint: string;
51
+ }
52
+ /**
53
+ * One complete drawing session: the contour pass an illustrator starts with,
54
+ * then the colour pass that fills it in.
55
+ */
56
+ export interface TraceShow {
57
+ sketch?: TraceDrawingPlan;
58
+ colour: TraceDrawingPlan;
59
+ }
60
+ /** Trace knobs shared by the decoded-pixels and encoded-bytes entry points. */
61
+ export interface TraceOptions {
62
+ /** Required: keep or drop the background. There is no automatic answer. */
63
+ removeBg: boolean;
64
+ preset?: TracePresetName;
65
+ fragments?: TraceFragments;
66
+ /** Palette size, 2–24. Also caps the number of visible colour layers. */
67
+ colors?: number;
68
+ /** RDP tolerance in work pixels; lower keeps more contour fidelity. */
69
+ epsilon?: number;
70
+ /** Regions under this area are merged into a neighbour. */
71
+ minArea?: number;
72
+ /** Long side cap for the work image; defaults to the calibrated 887. */
73
+ maxLongSide?: number;
74
+ /** SVG character budget; upstream default is 248000. */
75
+ budget?: number;
76
+ /** Derive a pencil sketch to play first; defaults to true. */
77
+ sketch?: boolean;
78
+ }
79
+ /** One trace over an encoded image. */
80
+ export interface TraceRequest extends TraceOptions {
81
+ /** Encoded image bytes (PNG is dependency free; JPEG/WebP need sharp). */
82
+ bytes: Uint8Array;
83
+ }
84
+ /**
85
+ * Trace an encoded raster into an SVG plus its replayable drawing plan.
86
+ * @param request - image bytes and trace knobs.
87
+ * @returns the SVG, the ordered plan, a model-facing summary and a tuning hint.
88
+ */
89
+ export declare function traceImageToDrawing(request: TraceRequest): Promise<TraceOutcome>;
90
+ /**
91
+ * Trace an already-decoded RGBA8 raster. Split out from `traceImageToDrawing`
92
+ * so tests can exercise the pipeline without encoding a PNG first.
93
+ *
94
+ * Produces the colour pass plus, unless disabled, a pencil pass derived from
95
+ * the same pixels. The sketch is best-effort: a picture with no edges worth
96
+ * drawing simply plays the colour pass alone.
97
+ */
98
+ export declare function traceRasterToDrawing(raster: {
99
+ width: number;
100
+ height: number;
101
+ data: Uint8Array;
102
+ }, options: TraceOptions): TraceOutcome;
@@ -0,0 +1,12 @@
1
+ /** Read-only route that hands one stored trace plan to the canvas. */
2
+ import type { IncomingMessage, ServerResponse } from 'node:http';
3
+ import type { TracePlanStore } from './trace-store.js';
4
+ export interface TraceRouteDeps {
5
+ store: TracePlanStore;
6
+ }
7
+ /**
8
+ * Serve one drawing plan by id. GET only: the plan is produced by the
9
+ * `draw_reference` tool and never written from the browser, so there is
10
+ * nothing to accept here.
11
+ */
12
+ export declare function serveTracePlan(req: IncomingMessage, res: ServerResponse, deps: TraceRouteDeps): Promise<void>;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Derive a pencil-sketch raster from a reference image.
3
+ *
4
+ * The tracer can only reproduce what is in the pixels, so "先起稿再上色" needs
5
+ * an actual contour drawing to reproduce. Spending a model call on one would be
6
+ * slow, non-deterministic and — for a picture the model has already been given
7
+ * — redundant. Derive it locally instead: grayscale, Sobel magnitude, an
8
+ * adaptive threshold, then a one-pixel dilation so the lines survive the
9
+ * downsampling the tracer does internally.
10
+ *
11
+ * The result is a black-on-white line drawing: the contour pass an illustrator
12
+ * makes before blocking in colour.
13
+ */
14
+ /** RGBA8 bitmap, the same shape the tracer consumes. */
15
+ export interface SketchRaster {
16
+ width: number;
17
+ height: number;
18
+ data: Uint8Array;
19
+ }
20
+ /**
21
+ * Build a line drawing from a raster.
22
+ * @param raster - source pixels (RGBA8).
23
+ * @param maxSide - long side to compute the edges at; defaults to 1200.
24
+ * @returns a black-on-white RGBA8 bitmap of the detected contours.
25
+ */
26
+ export declare function sketchRaster(raster: SketchRaster, maxSide?: number): SketchRaster;
@@ -0,0 +1,23 @@
1
+ import type { TraceShow } from './trace-drawing.js';
2
+ export interface TracePlanStoreOptions {
3
+ /** Directory for restart-surviving copies; omit to stay memory-only. */
4
+ dir?: string | undefined;
5
+ }
6
+ export declare class TracePlanStore {
7
+ private readonly entries;
8
+ private readonly dir;
9
+ constructor(options?: TracePlanStoreOptions);
10
+ /** Store one show and return the id the browser will use. */
11
+ put(show: TraceShow): Promise<string>;
12
+ /** The show behind an id: memory first, then the disk copy, else undefined. */
13
+ get(id: string): Promise<TraceShow | undefined>;
14
+ /** Write the disk copy; failures are logged and otherwise ignored. */
15
+ private persist;
16
+ /** Read one disk copy, dropping it when expired or malformed. */
17
+ private read;
18
+ private remove;
19
+ /** Drop expired entries, then the oldest ones past the cap, in memory and on disk. */
20
+ private evict;
21
+ /** Delete disk copies left behind by a previous host process. */
22
+ private evictDisk;
23
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Vendored from dsh-drawai v0.3.4 - https://github.com/fourzkw/dsh-drawai
3
+ * MIT License, Copyright (c) 2026 fourzkw.
4
+ * Copied verbatim from lib/raster.js apart from this header.
5
+ *
6
+ * PNG decoding is dependency free (node:zlib only). JPEG/GIF/WebP go through an
7
+ * optional sharp install, which this plugin does not rely on.
8
+ */
9
+ /**
10
+ * 位图解码 —— 把图片文件解成原始 RGBA 像素,供「逐像素矢量化」使用。
11
+ *
12
+ * 两条路:
13
+ * 1. **纯 Node 的 PNG 解码器**(零依赖,只用 node:zlib):PNG 是矢量化最常见的输入
14
+ * (截图、导出的角色图),自己解能保证"宿主装了什么依赖都能用"。
15
+ * 2. **可选 sharp**:非 PNG(JPEG / WebP / GIF…)自己没有解码器,装了 sharp 就用它。
16
+ * sharp 是可选依赖:没装时只报"这个格式解不开",不影响 PNG 那条主路。
17
+ *
18
+ * 解码结果是 `{ width, height, data }`,data 是 **RGBA8**(`width*height*4` 字节),
19
+ * 也就是矢量化的**唯一真相**:后面所有轮廓都从它算,中间不再碰文件。
20
+ */
21
+ /**
22
+ * 解一份 PNG 成 RGBA8。
23
+ *
24
+ * 支持:颜色类型 0/2/3/4/6、位深 1/2/4/8/16、Adam7 隔行、tRNS 透明。
25
+ * 不支持(会明确报错):颜色类型 1(已废弃)。
26
+ */
27
+ export declare function decodePng(bytes: any): {
28
+ width: number;
29
+ height: number;
30
+ data: Buffer<ArrayBuffer>;
31
+ };
32
+ /** 是不是能被本模块解开的图片(按文件头判,不看后缀)。 */
33
+ export declare function looksLikeRaster(bytes: any): boolean;
34
+ /**
35
+ * 解一份图片文件成 RGBA8。
36
+ *
37
+ * PNG 走自带解码器(零依赖、结果确定);其余格式试 sharp,没有就给可执行的建议。
38
+ */
39
+ export declare function decodeRaster(bytes: any): Promise<{
40
+ width: any;
41
+ height: any;
42
+ data: any;
43
+ }>;
@@ -0,0 +1,257 @@
1
+ /**
2
+ * Vendored from dsh-drawai v0.3.4 - https://github.com/fourzkw/dsh-drawai
3
+ * MIT License, Copyright (c) 2026 fourzkw.
4
+ * Copied verbatim from lib/trace-image.js apart from this header.
5
+ *
6
+ * Self-contained raster-to-SVG tracer: it takes RGBA pixels, quantizes with
7
+ * k-means, traces pixel-grid contours, simplifies with RDP, and emits one
8
+ * nonzero path per colour. With includeDrawing it also returns an ordered plan
9
+ * (largest area first) that a canvas can replay step by step.
10
+ */
11
+ /**
12
+ * 逐像素矢量化 —— 把一张位图变成一段内嵌 SVG 标记(DrawAI 的 svg 内容节点用)。
13
+ *
14
+ * 这里只有**像素进、SVG 出**,不碰文件系统、不碰 ctx:宿主工具与命令行脚本共用同一份。
15
+ *
16
+ * 管线(每一步都能在返回的 metrics 里看到数字):
17
+ * ① 工作图尺寸 = src/scale,再套 grid(宽)/ gridH(高)上限;透明像素合成到 bgColor
18
+ * ② 去背景:由调用方显式传 removeBg true/false(无 auto)。true 时先识纯色底再泛洪,识不到走近白回退
19
+ * ③ 分层 k-means(colorsDark 暗色 + colorsFill 填充)定调色板;暗像素进保护区
20
+ * ④ 3× 超采样归类 → 条件众数(高对比跳过)→ despeckle / minRegionArea(保护区不并)
21
+ * ⑤ 每色按连通域取闭合轮廓:像素**格边**上的有向图 + 左转跟随(区域恒在左侧)
22
+ * ⑥ RDP + 预算阶梯(受保护环不因 minLoopArea 丢弃)→ 每色一条 <path fill-rule="nonzero">
23
+ *
24
+ * 为什么是"格边跟随"而不是 marching squares:标签图在鞍点(对角相接)处 marching squares
25
+ * 要人为定连通性,而格边有向图本身就无歧义 —— 每条边只属于一个区域,走完一圈恰好回到起点。
26
+ * 代价是必须用 4 连通分区(对角相接算两个区域),见下面 connectedRegions 的注释。
27
+ */
28
+ /** 矢量化的默认参数(宿主工具与命令行共用)。 */
29
+ export declare const TRACE_DEFAULTS: {
30
+ preset: string;
31
+ colors: number;
32
+ colorsDark: number;
33
+ colorsFill: number;
34
+ grid: number;
35
+ gridH: number;
36
+ scale: number;
37
+ epsilon: number;
38
+ precision: number;
39
+ minArea: number;
40
+ minRegionArea: number;
41
+ protectLuma: number;
42
+ majorityContrast: number;
43
+ bgBright: number;
44
+ bgTol: number;
45
+ bgColor: number[];
46
+ bgSolidTol: number;
47
+ bgSolidBorderRatio: number;
48
+ seeds: number;
49
+ maxBytes: number;
50
+ includeLabels: boolean;
51
+ };
52
+ /**
53
+ * 命名预设:AI 先选场景,再按需覆盖单个字段。
54
+ * 合并顺序:TRACE_DEFAULTS ← preset ← 显式字段。
55
+ */
56
+ export declare const TRACE_PRESETS: {
57
+ default: {};
58
+ /** 插画 / 线稿:多留暗色、严保细线、轮廓更细 */
59
+ lineart: {
60
+ colorsDark: number;
61
+ protectLuma: number;
62
+ majorityContrast: number;
63
+ minArea: number;
64
+ epsilon: number;
65
+ precision: number;
66
+ };
67
+ /** 照片 / 渐变:少暗色配额、碎块并多一点、轮廓可粗 */
68
+ photo: {
69
+ colors: number;
70
+ colorsDark: number;
71
+ protectLuma: number;
72
+ majorityContrast: number;
73
+ minArea: number;
74
+ epsilon: number;
75
+ };
76
+ /** 图标 / 简单截图:少色 + 降采样,压字符数 */
77
+ simple: {
78
+ colors: number;
79
+ colorsDark: number;
80
+ scale: number;
81
+ grid: number;
82
+ epsilon: number;
83
+ minArea: number;
84
+ protectLuma: number;
85
+ };
86
+ };
87
+ /** 合法预设名列表(给报错 / 提示用)。 */
88
+ export declare const TRACE_PRESET_NAMES: string[];
89
+ /** 按用户参考图校准:保持同一棱角化色块管线,主要以采样密度区分三档。 */
90
+ export declare const TRACE_FRAGMENT_LEVELS: Readonly<{
91
+ low: Readonly<{
92
+ resolutionRatio: number;
93
+ tolerance: 0.1;
94
+ }>;
95
+ medium: Readonly<{
96
+ resolutionRatio: number;
97
+ tolerance: 0.08;
98
+ }>;
99
+ high: Readonly<{
100
+ resolutionRatio: 1;
101
+ tolerance: 0.04;
102
+ }>;
103
+ }>;
104
+ export declare function traceRasterForToolbar(raster: any, raw?: {}): any;
105
+ /**
106
+ * 合并默认值 + 预设 + 显式覆盖。未知 preset 抛错(让 AI 立刻改,而不是静默当 default)。
107
+ * @returns {{options:object, preset:string}}
108
+ */
109
+ export declare function resolveTraceOptions(rawOptions: any): {
110
+ options: any;
111
+ preset: any;
112
+ };
113
+ /**
114
+ * 根据 metrics 生成一句调参建议(给 AI 读,不是给用户的长文)。
115
+ */
116
+ export declare function hintTraceTune(metrics: any): string;
117
+ /**
118
+ * 把普通 JSON 数据收成 DSH 工具返回值能过关的"无损 JSON":
119
+ * · 丢掉值为 undefined 的自有属性(`{crop:undefined}` 会被 isJsonValue 判死刑,
120
+ * 而 JSON.stringify 却会默默省略 —— 这正是 traceImage 回执曾触发
121
+ * `tool "diagram_apply" returned invalid output: value is not lossless JSON` 的根因)
122
+ * · 把 -0 收成 0(DSH 的 walkJsonValue 同样拒 -0)
123
+ * · 非有限数字 → 0(宁可变钝,也不让整次工具调用被宿主打回)
124
+ */
125
+ export declare function toLosslessJson(value: any): any;
126
+ /**
127
+ * 压缩给 AI 的结构化调参回执(diagram_apply.trace[])。
128
+ *
129
+ * 可选字段(image / nodeId / crop)**缺就不要挂键** —— 宿主对工具输出走
130
+ * lossless JSON 校验,自有属性值为 undefined 会整次失败。
131
+ */
132
+ export declare function summarizeTraceForAi(metrics: any, extra: any): any;
133
+ /**
134
+ * 位图 → SVG 标记。
135
+ *
136
+ * @param {{width:number,height:number,data:Buffer|Uint8Array}} raster RGBA8
137
+ * @param {object} [rawOptions] 见 TRACE_DEFAULTS / TRACE_PRESETS(可用 preset)
138
+ * @returns {{svg:string, metrics:object}}
139
+ */
140
+ export declare function traceRasterToSvg(raster: any, rawOptions: any): {
141
+ labels: {
142
+ width: number;
143
+ height: number;
144
+ colors: number;
145
+ palette: string[];
146
+ labels: string;
147
+ } | null;
148
+ metrics: {
149
+ preset: any;
150
+ source: {
151
+ width: any;
152
+ height: any;
153
+ };
154
+ work: {
155
+ width: number;
156
+ height: number;
157
+ scale: number;
158
+ };
159
+ scaleRequested: number;
160
+ scaleApplied: number;
161
+ grid: number;
162
+ gridH: number;
163
+ bgColor: any[];
164
+ sizeNotes: string;
165
+ colors: number;
166
+ colorsDark: number;
167
+ colorsFill: any;
168
+ darkSamples: number;
169
+ fillSamples: any;
170
+ protectLuma: number;
171
+ protectPixels: number;
172
+ fgRelabeledFromBg: number;
173
+ bgForced: number;
174
+ bgRemoved: boolean;
175
+ bgDetect: {
176
+ hasSolid: boolean;
177
+ mode: string;
178
+ matchRatio: number;
179
+ kind: null;
180
+ color: null;
181
+ };
182
+ majorityContrast: number;
183
+ majoritySkipped: number;
184
+ majorityApplied: number;
185
+ palette: string[];
186
+ backgroundPixels: number;
187
+ foregroundPixels: number;
188
+ despeckle: {
189
+ mergedPixels: number;
190
+ blocksMerged: number;
191
+ blocks: number;
192
+ protectedSkipped: number;
193
+ };
194
+ regionMerge: {
195
+ mergedPixels: number;
196
+ blocksMerged: number;
197
+ blocks: number;
198
+ protectedSkipped: number;
199
+ };
200
+ regions: number;
201
+ regionsProtected: number;
202
+ loops: number;
203
+ paths: number;
204
+ loopsKept: number;
205
+ fragments: number;
206
+ loopsProtectedKept: number;
207
+ drawnPixels: number | null;
208
+ totalPixels: number;
209
+ exactPixelCoverage: boolean;
210
+ labelPartitionComplete: boolean;
211
+ coverageBasis: string;
212
+ loopsDropped: number;
213
+ budgetExceeded: boolean;
214
+ appliedEpsilon: any;
215
+ svgChars: number;
216
+ budget: any;
217
+ attempts: number;
218
+ paletteAreaSum: number;
219
+ optionsApplied: {
220
+ preset: any;
221
+ colors: number;
222
+ colorsDark: number;
223
+ colorsFill: any;
224
+ grid: number;
225
+ gridH: number;
226
+ scale: number;
227
+ epsilon: any;
228
+ precision: any;
229
+ minArea: number;
230
+ minRegionArea: number;
231
+ protectLuma: number;
232
+ majorityContrast: number;
233
+ removeBg: string;
234
+ bgSolidTol: any;
235
+ bgSolidBorderRatio: any;
236
+ };
237
+ };
238
+ drawing?: {
239
+ viewBox: number[];
240
+ fills: string[];
241
+ steps: {
242
+ layer: number;
243
+ d: any;
244
+ area: any;
245
+ }[];
246
+ };
247
+ svg: string;
248
+ };
249
+ /**
250
+ * 把 SVG 标记编码进 drawio 的 `image=` 值(`data:image/svg+xml,<百分号编码>`)。
251
+ *
252
+ * 为什么用百分号编码而不是 base64:编码后的串里一个 `;` 都没有,而 drawio 与本内核的
253
+ * style 解析都是按 `;` 分段 —— base64 形态的 `data:image/svg+xml;base64,` 那个分号是解析器的雷。
254
+ * 这里编得比 JSON 严格一点(`<` `>` `#` `%` `"` 和空格),换来的好处是:不管宿主把它塞进
255
+ * 属性还是直接写进 style,都不会有歧义。
256
+ */
257
+ export declare function svgToImageValue(svg: any): string;
@@ -0,0 +1,4 @@
1
+ import type { ConnectionRequestRejection, ConnectionTrustRequest } from '@deepseek-ai/dsh-client-connection';
2
+ import type { WebRoute } from '@deepseek-ai/dsh-host-webserver';
3
+ export type WebAdmission = (request: ConnectionTrustRequest) => ConnectionRequestRejection;
4
+ export declare function withWebAdmission(route: WebRoute, admission: () => WebAdmission | undefined): WebRoute;