dsh-dialog-width 0.0.1

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/lib/index.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * dsh-dialog-width — server half.
3
+ *
4
+ * Registers the `dialog-width` settings namespace so users can control the
5
+ * conversation column width either from the Settings panel or by editing the
6
+ * settings document directly (settings.yaml `dialog-width:` section). All
7
+ * rendering work happens in the browser bundle (`src/client`), which reads
8
+ * and writes this namespace through the same-origin route mounted here —
9
+ * the Web settings RPC only exposes a fixed allowlist of namespaces since
10
+ * rc.6, so a custom route is the supported way for a plugin to own a
11
+ * configuration page.
12
+ * @module dsh-dialog-width
13
+ */
14
+ import { DIALOG_WIDTH_SETTINGS_NAMESPACE, Config, } from "./config.js";
15
+ import { DialogWidthWebBackend, installDialogWidthWeb } from "./web.js";
16
+ export const name = 'dsh-dialog-width';
17
+ /** Required services: the settings seam is the whole server-side surface. */
18
+ export const inject = ['settings', 'web'];
19
+ export function apply(ctx) {
20
+ ctx.settings.register(DIALOG_WIDTH_SETTINGS_NAMESPACE, Config, {
21
+ applies: 'live',
22
+ });
23
+ // The browser Settings panel talks to the namespace through this same-origin
24
+ // route (the Web settings RPC only exposes a fixed allowlist since rc.6).
25
+ installDialogWidthWeb(ctx, new DialogWidthWebBackend(ctx));
26
+ ctx.logger.info('[dsh-dialog-width] settings namespace registered and Web routes mounted');
27
+ }
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EACL,+BAA+B,EAC/B,MAAM,GACP,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAEvE,MAAM,CAAC,MAAM,IAAI,GAAG,kBAAkB,CAAA;AAEtC,6EAA6E;AAC7E,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAA;AAEzC,MAAM,UAAU,KAAK,CAAC,GAAY;IAChC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,+BAA+B,EAAE,MAAM,EAAE;QAC7D,OAAO,EAAE,MAAM;KAChB,CAAC,CAAA;IAEF,6EAA6E;IAC7E,0EAA0E;IAC1E,qBAAqB,CAAC,GAAG,EAAE,IAAI,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAA;IAE1D,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAA;AAC5F,CAAC"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * dsh-dialog-width — conversation-width override (browser half).
3
+ *
4
+ * When the user turns "plugin width control" on, this module:
5
+ *
6
+ * 1. Hides DSH's native 40 px hover drag handles. The handles live in a
7
+ * CSS-Modules file (`ConversationRoot.module.css`) whose class names are
8
+ * build-time-hashed, so a global stylesheet cannot target them by class —
9
+ * it MUST use the stable `data-width-handle` attribute selector.
10
+ *
11
+ * 2. Drives DSH's own shared width axis instead of forking it. The
12
+ * conversation root declares the single source of truth
13
+ * (`ConversationRoot.module.css`, `.root`):
14
+ *
15
+ * --dsh-chat-content-width: var(--dsh-chat-user-width, clamp(680px, calc(var(--dsh-conversation-column-width, 0px) * 0.64), 920px));
16
+ * --dsh-composer-card-max-width: calc(var(--dsh-chat-content-width) + 32px);
17
+ *
18
+ * Every consumer — the transcript column (`data-chat-flow`), message
19
+ * bubbles, wide-table bleed, the back-to-bottom control, the composer
20
+ * card, and the dock/stats line — reads those two variables, so forcing
21
+ * `--dsh-chat-user-width` keeps the input card and the conversation area
22
+ * in lockstep by construction. The plugin never sets max-widths itself.
23
+ *
24
+ * 3. Reproduces DSH's narrow-viewport clamp in CSS. Natively
25
+ * (`ConversationRoot.tsx`, `resolveContentWidth`) a stored preference is
26
+ * re-clamped against the live column width — published as
27
+ * `--dsh-conversation-column-width` by a ResizeObserver — so opening the
28
+ * sidebar narrows the content instead of letting it overflow. This module
29
+ * declares the same clamp declaratively on the conversation root:
30
+ *
31
+ * --dsh-chat-user-width: min(<width>px, max(640px, calc(var(--dsh-conversation-column-width, 99999px) - 2 * <sideMargin>px)));
32
+ *
33
+ * i.e. the column never claims more than the dialog width, and never
34
+ * leaves less than `sideMargin` of whitespace on either side; 640px is
35
+ * DSH's own content floor (CONTENT_MIN). The var() substitution happens
36
+ * on the conversation root — the same element DSH writes the live column
37
+ * width on — so the clamp tracks sidebar toggles and window resizes with
38
+ * zero JS. The declaration is `!important` so it also beats DSH's inline
39
+ * re-publication of `--dsh-chat-user-width` on the same element.
40
+ *
41
+ * 4. Mirrors the chosen px into the shared localStorage slot
42
+ * (`dsh.conversation.contentWidth`) so toggling plugin-width OFF surfaces
43
+ * the user's last choice in the native drag handles — the switch is
44
+ * value-preserving in both directions.
45
+ *
46
+ * When the user turns the feature OFF, the installer disposes: the handle
47
+ * rule and the width-axis override are removed and the native handles take
48
+ * over from whatever px the user last picked.
49
+ *
50
+ * The conversation root cannot be targeted by a stable attribute of its own
51
+ * (it only carries `data-phase`), so the override anchors on the stable
52
+ * `data-conversation-scroll` descendant: `div:has([data-conversation-scroll])`
53
+ * matches exactly the ancestors of the scroll body, and the innermost
54
+ * declaration that matters — the conversation root — is where DSH publishes
55
+ * the live column width.
56
+ * @module dsh-dialog-width/client/conversation-width
57
+ */
58
+ export interface ConversationWidthController {
59
+ /** Update the applied width / side margin (px) without reinstalling the stylesheet. */
60
+ setWidth(widthPx: number, sideMargin: number): void;
61
+ /** Remove the injected stylesheet + clear the :root var. */
62
+ dispose(): void;
63
+ }
64
+ /**
65
+ * Install the width-override stylesheet. Idempotent: a second call with the
66
+ * same id returns the existing controller.
67
+ * @param widthPx - the plugin's chosen column width in px.
68
+ * @param sideMargin - whitespace in px to keep on each side of the column.
69
+ * @returns a controller exposing `setWidth` + `dispose`.
70
+ */
71
+ export declare function installConversationWidthStyles(widthPx: number, sideMargin: number): ConversationWidthController;
72
+ //# sourceMappingURL=conversation-width.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-width.d.ts","sourceRoot":"","sources":["../../../src/client/conversation-width.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AAgCH,MAAM,WAAW,2BAA2B;IAC1C,uFAAuF;IACvF,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACnD,4DAA4D;IAC5D,OAAO,IAAI,IAAI,CAAA;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,2BAA2B,CAgC/G"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * dsh-dialog-width — browser half.
3
+ *
4
+ * Reads and writes the `dialog-width` settings namespace through the
5
+ * same-origin route served by the server half, applies the chosen dialog
6
+ * width live via a runtime `<style>` element, and renders the Settings
7
+ * panel section that edits it.
8
+ */
9
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
10
+ interface TweaksValue {
11
+ /** Dialog width in px; clamped to [600, 1600]. Keep in sync with src/config.ts. */
12
+ dialogWidth?: number;
13
+ /** Whether the plugin's width control owns the column (vs. native handles). */
14
+ usePluginWidth?: boolean;
15
+ /** Side margin in px; minimum 32. Keep in sync with src/config.ts. */
16
+ sideMargin?: number;
17
+ }
18
+ declare const en: {
19
+ readonly nav: "Dialog width";
20
+ readonly settingsTitle: "Dialog width";
21
+ readonly settingsIntro: "Control the conversation column width — either let the plugin drive it with a precise pixel value, or use DSH's native drag handles.";
22
+ readonly sectionLayout: "Layout";
23
+ readonly dialogWidth: "Dialog width";
24
+ readonly dialogWidthHint: "Number between 600 and 1600 px; 748 is DSH's default column width, larger values widen it.";
25
+ readonly presetDefault: "Default";
26
+ readonly presetWide: "Wide";
27
+ readonly presetWideXl: "Extra wide";
28
+ readonly usePluginWidth: "Plugin width control";
29
+ readonly usePluginWidthHint: "When ON, the width input / presets above drive the column and DSH's native drag handles are hidden. When OFF, DSH's native handles own the column; the width input mirrors their value.";
30
+ readonly usePluginWidthOn: "On";
31
+ readonly usePluginWidthOff: "Off";
32
+ readonly sideMargin: "Side margin";
33
+ readonly sideMarginHint: "Whitespace in px kept on each side of the conversation area. The column is clamped to the dialog width and narrows when the sidebar opens or the window shrinks, never hugging the edges. Minimum 32 px.";
34
+ readonly defaultAction: "Default";
35
+ readonly applied: "Applied";
36
+ readonly unavailable: "Settings unavailable.";
37
+ readonly loading: "Loading…";
38
+ readonly readOnly: "The active Settings provider is read-only.";
39
+ };
40
+ type LocaleKey = keyof typeof en;
41
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
42
+ interface LocaleNamespaceMap {
43
+ /** dsh-dialog-width Settings copy. */
44
+ 'dialog-width': LocaleKey;
45
+ }
46
+ }
47
+ /** Client-side snapshot store fed by the same-origin Settings route. */
48
+ interface SettingsState {
49
+ status: 'loading' | 'ready' | 'error';
50
+ writable: boolean;
51
+ value: TweaksValue | undefined;
52
+ revision: number | undefined;
53
+ error?: string;
54
+ }
55
+ /** Small external store shared by the Settings route and the CSS engine. */
56
+ export declare class SettingsClient {
57
+ private state;
58
+ private listeners;
59
+ private generation;
60
+ subscribe: (listener: () => void) => (() => void);
61
+ getSnapshot: () => SettingsState;
62
+ private publish;
63
+ load(): Promise<void>;
64
+ private post;
65
+ set(field: string, value: unknown): Promise<void>;
66
+ unset(field: string): Promise<void>;
67
+ }
68
+ /** Required client services: slots (settings.section) and locale. */
69
+ export declare const inject: string[];
70
+ export declare function apply(ctx: ClientContext): void;
71
+ export {};
72
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAiBnE,UAAU,WAAW;IACnB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAoBD,QAAA,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;CAqBE,CAAA;AAEV,KAAK,SAAS,GAAG,MAAM,OAAO,EAAE,CAAA;AA2BhC,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,sCAAsC;QACtC,cAAc,EAAE,SAAS,CAAA;KAC1B;CACF;AA8GD,wEAAwE;AACxE,UAAU,aAAa;IACrB,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,CAAA;IACrC,QAAQ,EAAE,OAAO,CAAA;IACjB,KAAK,EAAE,WAAW,GAAG,SAAS,CAAA;IAC9B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,4EAA4E;AAC5E,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAA+F;IAC5G,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,UAAU,CAAI;IAEtB,SAAS,aAAc,MAAM,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC,CAG/C;IAED,WAAW,QAAO,aAAa,CAAc;IAE7C,OAAO,CAAC,OAAO;IAKT,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAkBb,IAAI;IAgBZ,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjD,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG1C;AAED,qEAAqE;AACrE,eAAO,MAAM,MAAM,UAAsB,CAAA;AAmMzC,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CA2C9C"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * dsh-dialog-width — configuration.
3
+ *
4
+ * Owns the `dialog-width` settings namespace: a single toggle (plugin width
5
+ * control) plus the dialog width input (px). Everything else is owned by the
6
+ * host or other plugins.
7
+ * @module dsh-dialog-width/config
8
+ */
9
+ import type Schema from '@deepseek-ai/schemastery';
10
+ /** Settings document namespace owned by this plugin. */
11
+ export declare const DIALOG_WIDTH_SETTINGS_NAMESPACE = "dialog-width";
12
+ /** Raw user-facing configuration (partial inputs receive schema defaults). */
13
+ export interface DialogWidthConfig {
14
+ /**
15
+ * Conversation column width in px. The plugin's own width input / preset
16
+ * row reads & writes this field when "plugin width control" is on (see
17
+ * `usePluginWidth`); when off, the field still mirrors the user's chosen
18
+ * px value to the shared storage slot so flipping the switch never loses
19
+ * it. Clamped to [600, 1600] on read.
20
+ */
21
+ dialogWidth?: number;
22
+ /**
23
+ * Whether the plugin's own column-width input owns the conversation width
24
+ * axis. On (default): the plugin writes `--dsh-chat-user-width` directly
25
+ * and hides the native 40 px hover handles. Off: the native drag handles
26
+ * own the axis (clamp(680, col×0.64, 920)) and the plugin's width input
27
+ * mirrors its value to the shared localStorage so flipping the switch back
28
+ * on restores the same px.
29
+ */
30
+ usePluginWidth?: boolean;
31
+ /**
32
+ * Whitespace in px kept on each side of the conversation area. The width
33
+ * axis is clamped to min(dialogWidth, liveColumn − 2 × sideMargin), so the
34
+ * content narrows — together with the composer card — when the sidebar
35
+ * opens or the window shrinks, never hugging the edges. Minimum 32 px.
36
+ */
37
+ sideMargin?: number;
38
+ }
39
+ /** Dialog width in px. 600 is the chat-column minimum, 1600 the soft cap. */
40
+ export declare const MIN_DIALOG_WIDTH = 600;
41
+ export declare const MAX_DIALOG_WIDTH = 1600;
42
+ /** 748 matches the stock DSH column. */
43
+ export declare const DEFAULT_DIALOG_WIDTH = 748;
44
+ /**
45
+ * Plugin width control defaults to ON: existing settings documents never had
46
+ * this field, so the default must match what users saw before the native
47
+ * handles shipped — the plugin owning the column.
48
+ */
49
+ export declare const DEFAULT_USE_PLUGIN_WIDTH = true;
50
+ /** Default side margin in px — 50 gives a comfortable gap on each side. */
51
+ export declare const DEFAULT_SIDE_MARGIN = 50;
52
+ /** Minimum side margin in px — below 32 the gap becomes too tight. */
53
+ export declare const MIN_SIDE_MARGIN = 32;
54
+ /**
55
+ * localStorage slot the native WidthHandle reads/writes; kept here so a
56
+ * future rename of the host key only needs touching one place. We mirror
57
+ * the plugin's chosen px value here too so toggling plugin-width off
58
+ * surfaces the user's last choice in the native handle.
59
+ */
60
+ export declare const CONVERSATION_WIDTH_STORAGE_KEY = "dsh.conversation.contentWidth";
61
+ /** Configuration schema with documented defaults. */
62
+ export declare const Config: Schema<DialogWidthConfig>;
63
+ /** Configuration after static validation, with every default materialized. */
64
+ export interface ResolvedDialogWidthConfig {
65
+ /** Dialog width in px (748 = the stock DSH column). */
66
+ dialogWidth: number;
67
+ /** Whether the plugin's width control owns the column (vs. native handles). */
68
+ usePluginWidth: boolean;
69
+ /** Side margin in px applied to both sides of the conversation column. */
70
+ sideMargin: number;
71
+ }
72
+ /** Resolve a partial config into a fully defaulted value. */
73
+ export declare function resolveConfig(config?: DialogWidthConfig): ResolvedDialogWidthConfig;
74
+ /** Normalize a dialog width value (legacy strings included) to px. */
75
+ export declare function resolveDialogWidth(value: number | undefined): number;
76
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,MAAM,MAAM,0BAA0B,CAAA;AAElD,wDAAwD;AACxD,eAAO,MAAM,+BAA+B,iBAAiB,CAAA;AAE7D,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,6EAA6E;AAC7E,eAAO,MAAM,gBAAgB,MAAM,CAAA;AACnC,eAAO,MAAM,gBAAgB,OAAO,CAAA;AACpC,wCAAwC;AACxC,eAAO,MAAM,oBAAoB,MAAM,CAAA;AAEvC;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,OAAO,CAAA;AAE5C,2EAA2E;AAC3E,eAAO,MAAM,mBAAmB,KAAK,CAAA;AACrC,sEAAsE;AACtE,eAAO,MAAM,eAAe,KAAK,CAAA;AAEjC;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,kCAAkC,CAAA;AAE7E,qDAAqD;AACrD,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,iBAAiB,CAI3C,CAAA;AAEF,8EAA8E;AAC9E,MAAM,WAAW,yBAAyB;IACxC,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAA;IACnB,+EAA+E;IAC/E,cAAc,EAAE,OAAO,CAAA;IACvB,0EAA0E;IAC1E,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,MAAM,GAAE,iBAAsB,GAAG,yBAAyB,CAKvF;AAED,sEAAsE;AACtE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAKpE"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * dsh-dialog-width — server half.
3
+ *
4
+ * Registers the `dialog-width` settings namespace so users can control the
5
+ * conversation column width either from the Settings panel or by editing the
6
+ * settings document directly (settings.yaml `dialog-width:` section). All
7
+ * rendering work happens in the browser bundle (`src/client`), which reads
8
+ * and writes this namespace through the same-origin route mounted here —
9
+ * the Web settings RPC only exposes a fixed allowlist of namespaces since
10
+ * rc.6, so a custom route is the supported way for a plugin to own a
11
+ * configuration page.
12
+ * @module dsh-dialog-width
13
+ */
14
+ import type { Context } from '@deepseek-ai/cordis';
15
+ export declare const name = "dsh-dialog-width";
16
+ /** Required services: the settings seam is the whole server-side surface. */
17
+ export declare const inject: string[];
18
+ export declare function apply(ctx: Context): void;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAOlD,eAAO,MAAM,IAAI,qBAAqB,CAAA;AAEtC,6EAA6E;AAC7E,eAAO,MAAM,MAAM,UAAsB,CAAA;AAEzC,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAUxC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * dsh-dialog-width — optional Web routes.
3
+ *
4
+ * The browser Settings panel reads and writes the `dialog-width` namespace
5
+ * through this same-origin route, because the Web settings RPC only exposes
6
+ * a fixed allowlist of namespaces (hardcoded in dsh-host-apiproxy since
7
+ * rc.6). The route proxies to the real `ctx.settings` service, so the
8
+ * settings document (settings.yaml) stays the single source of truth and
9
+ * hand edits keep working.
10
+ * @module dsh-dialog-width/web
11
+ */
12
+ import type { IncomingMessage, ServerResponse } from 'node:http';
13
+ import type { Context } from '@deepseek-ai/cordis';
14
+ /** Exact route used by the browser Settings page. */
15
+ export declare const SETTINGS_ROUTE = "/_dsh/dialog-width/settings";
16
+ /** Public Settings snapshot; no secrets exist in this namespace. */
17
+ export interface DialogWidthSnapshot {
18
+ writable: boolean;
19
+ value: unknown;
20
+ revision: number;
21
+ }
22
+ type JsonResponse<T> = {
23
+ ok: true;
24
+ value: T;
25
+ } | {
26
+ ok: false;
27
+ error: {
28
+ code: string;
29
+ message: string;
30
+ };
31
+ };
32
+ /** Accept state-changing requests only from the DSH Web application's origin. */
33
+ export declare function sameOriginPost(req: IncomingMessage): boolean;
34
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
35
+ export declare function json<T>(res: ServerResponse, status: number, body: JsonResponse<T>): void;
36
+ export declare function requestError(res: ServerResponse, status: number, code: string, message: string): void;
37
+ export declare function readJson(req: IncomingMessage, maxBytes?: number): Promise<unknown>;
38
+ export declare function messageOf(error: unknown): string;
39
+ /** Same-origin Settings read/write handler. */
40
+ export declare class DialogWidthWebBackend {
41
+ private readonly ctx;
42
+ constructor(ctx: Context);
43
+ private descriptor;
44
+ private snapshot;
45
+ /** Handle the exact Settings route. */
46
+ handle(req: IncomingMessage, res: ServerResponse): Promise<void>;
47
+ }
48
+ /**
49
+ * Attach the Settings route whenever a webServer service is present.
50
+ * @param ctx - plugin context owning route effects.
51
+ * @param backend - Settings handler.
52
+ */
53
+ export declare function installDialogWidthWeb(ctx: Context, backend: DialogWidthWebBackend): void;
54
+ export {};
55
+ //# sourceMappingURL=web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAMlD,qDAAqD;AACrD,eAAO,MAAM,cAAc,gCAAgC,CAAA;AAE3D,oEAAoE;AACpE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,OAAO,CAAA;IACjB,KAAK,EAAE,OAAO,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB;AAiBD,KAAK,YAAY,CAAC,CAAC,IACf;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GACtB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAA;AAE3D,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAa5D;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,wBAAgB,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,CAQxF;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAErG;AAED,wBAAsB,QAAQ,CAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,SAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAa3F;AAkBD,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGhD;AAED,+CAA+C;AAC/C,qBAAa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,OAAO;IAEzC,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,QAAQ;IAShB,uCAAuC;IACjC,MAAM,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CA2CvE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAUxF"}
package/lib/web.js ADDED
@@ -0,0 +1,169 @@
1
+ /**
2
+ * dsh-dialog-width — optional Web routes.
3
+ *
4
+ * The browser Settings panel reads and writes the `dialog-width` namespace
5
+ * through this same-origin route, because the Web settings RPC only exposes
6
+ * a fixed allowlist of namespaces (hardcoded in dsh-host-apiproxy since
7
+ * rc.6). The route proxies to the real `ctx.settings` service, so the
8
+ * settings document (settings.yaml) stays the single source of truth and
9
+ * hand edits keep working.
10
+ * @module dsh-dialog-width/web
11
+ */
12
+ import { SettingsConflictError } from '@deepseek-ai/dsh-settings';
13
+ import { DIALOG_WIDTH_SETTINGS_NAMESPACE } from "./config.js";
14
+ /** Exact route used by the browser Settings page. */
15
+ export const SETTINGS_ROUTE = '/_dsh/dialog-width/settings';
16
+ /** Accept state-changing requests only from the DSH Web application's origin. */
17
+ export function sameOriginPost(req) {
18
+ const fetchSite = req.headers['sec-fetch-site'];
19
+ if (fetchSite === 'cross-site')
20
+ return false;
21
+ const origin = req.headers.origin;
22
+ if (origin === undefined)
23
+ return fetchSite === 'same-origin' || fetchSite === 'same-site' || fetchSite === 'none';
24
+ const host = req.headers.host;
25
+ if (host === undefined)
26
+ return false;
27
+ try {
28
+ const parsed = new URL(origin);
29
+ return (parsed.protocol === 'http:' || parsed.protocol === 'https:') && parsed.host === host;
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ export function isRecord(value) {
36
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
37
+ }
38
+ export function json(res, status, body) {
39
+ const bytes = Buffer.from(JSON.stringify(body));
40
+ res.setHeader('Content-Type', 'application/json; charset=utf-8');
41
+ res.setHeader('Content-Length', String(bytes.length));
42
+ res.setHeader('Cache-Control', 'no-store');
43
+ res.setHeader('X-Content-Type-Options', 'nosniff');
44
+ res.writeHead(status);
45
+ res.end(bytes);
46
+ }
47
+ export function requestError(res, status, code, message) {
48
+ json(res, status, { ok: false, error: { code, message } });
49
+ }
50
+ export async function readJson(req, maxBytes = 16 * 1024) {
51
+ const contentType = req.headers['content-type']?.split(';', 1)[0]?.trim().toLowerCase();
52
+ if (contentType !== 'application/json')
53
+ throw new TypeError('Content-Type must be application/json');
54
+ const chunks = [];
55
+ let bytes = 0;
56
+ for await (const chunk of req) {
57
+ const part = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
58
+ bytes += part.length;
59
+ if (bytes > maxBytes)
60
+ throw new RangeError(`request body exceeds ${maxBytes} bytes`);
61
+ chunks.push(part);
62
+ }
63
+ if (chunks.length === 0)
64
+ throw new TypeError('request body is empty');
65
+ return JSON.parse(Buffer.concat(chunks).toString('utf8'));
66
+ }
67
+ function parseRequest(value) {
68
+ if (!isRecord(value) || typeof value.action !== 'string')
69
+ throw new TypeError('action is required');
70
+ if (typeof value.expectedRevision !== 'number' || !Number.isSafeInteger(value.expectedRevision) || value.expectedRevision < 0) {
71
+ throw new TypeError('expectedRevision must be a non-negative integer');
72
+ }
73
+ const field = value.field;
74
+ if (typeof field !== 'string' || field.length === 0)
75
+ throw new TypeError('field must be a non-empty string');
76
+ if (value.action === 'unset') {
77
+ return { action: 'unset', field, expectedRevision: value.expectedRevision };
78
+ }
79
+ if (value.action === 'set') {
80
+ return { action: 'set', field, value: value.value, expectedRevision: value.expectedRevision };
81
+ }
82
+ throw new TypeError(`unsupported action: ${value.action}`);
83
+ }
84
+ export function messageOf(error) {
85
+ if (error instanceof Error)
86
+ return error.message;
87
+ return String(error);
88
+ }
89
+ /** Same-origin Settings read/write handler. */
90
+ export class DialogWidthWebBackend {
91
+ ctx;
92
+ constructor(ctx) {
93
+ this.ctx = ctx;
94
+ }
95
+ descriptor() {
96
+ const row = this.ctx.settings.describe().find(candidate => candidate.ns === DIALOG_WIDTH_SETTINGS_NAMESPACE);
97
+ if (row === undefined)
98
+ throw new Error('dialog-width settings namespace is not registered');
99
+ return row;
100
+ }
101
+ snapshot() {
102
+ const descriptor = this.descriptor();
103
+ return {
104
+ writable: this.ctx.settings.writable,
105
+ value: descriptor.value,
106
+ revision: descriptor.revision,
107
+ };
108
+ }
109
+ /** Handle the exact Settings route. */
110
+ async handle(req, res) {
111
+ if (req.method === 'GET') {
112
+ try {
113
+ json(res, 200, { ok: true, value: this.snapshot() });
114
+ }
115
+ catch (error) {
116
+ this.ctx.logger.warn('dsh-dialog-width Settings snapshot failed: %s', messageOf(error));
117
+ requestError(res, 503, 'settings-unavailable', 'Dialog width settings are unavailable');
118
+ }
119
+ return;
120
+ }
121
+ if (req.method !== 'POST') {
122
+ res.setHeader('Allow', 'GET, POST');
123
+ requestError(res, 405, 'method-not-allowed', 'Use GET or POST');
124
+ return;
125
+ }
126
+ if (!sameOriginPost(req)) {
127
+ requestError(res, 403, 'origin-rejected', 'The request must originate from this DSH Web application');
128
+ return;
129
+ }
130
+ let parsed;
131
+ try {
132
+ parsed = parseRequest(await readJson(req));
133
+ }
134
+ catch (error) {
135
+ requestError(res, error instanceof RangeError ? 413 : 400, 'invalid-request', messageOf(error));
136
+ return;
137
+ }
138
+ try {
139
+ if (parsed.action === 'set') {
140
+ await this.ctx.settings.update(DIALOG_WIDTH_SETTINGS_NAMESPACE, { [parsed.field]: parsed.value }, parsed.expectedRevision);
141
+ }
142
+ else {
143
+ await this.ctx.settings.mutate(DIALOG_WIDTH_SETTINGS_NAMESPACE, [{ op: 'unset', path: [parsed.field] }], parsed.expectedRevision);
144
+ }
145
+ json(res, 200, { ok: true, value: this.snapshot() });
146
+ }
147
+ catch (error) {
148
+ const conflict = error instanceof SettingsConflictError;
149
+ requestError(res, conflict ? 409 : 400, conflict ? 'settings-conflict' : 'settings-rejected', messageOf(error));
150
+ }
151
+ }
152
+ }
153
+ /**
154
+ * Attach the Settings route whenever a webServer service is present.
155
+ * @param ctx - plugin context owning route effects.
156
+ * @param backend - Settings handler.
157
+ */
158
+ export function installDialogWidthWeb(ctx, backend) {
159
+ ctx.inject(['webServer'], (webCtx) => {
160
+ webCtx.effect(() => {
161
+ return webCtx.webServer.register({
162
+ kind: 'exact',
163
+ path: SETTINGS_ROUTE,
164
+ handler: (req, res) => backend.handle(req, res),
165
+ });
166
+ }, 'dsh-dialog-width: Web routes');
167
+ });
168
+ }
169
+ //# sourceMappingURL=web.js.map
package/lib/web.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,104 @@
1
+ {
2
+ "name": "dsh-dialog-width",
3
+ "version": "0.0.1",
4
+ "description": "DSH plugin: control the conversation column width — a pixel-value input (600–1600 px) with presets, plus a switch to toggle between plugin-driven width and DSH's native drag handles. Requires DSH v0.1.2-alpha.5+.",
5
+ "keywords": [
6
+ "dsh",
7
+ "deepseek",
8
+ "deepseek-ai",
9
+ "cordis",
10
+ "plugin",
11
+ "dialog-width",
12
+ "chat-ui"
13
+ ],
14
+ "type": "module",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/zhj9709/dsh-dialog-width.git"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "main": "lib/index.js",
23
+ "types": "lib/types/index.d.ts",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./lib/types/index.d.ts",
27
+ "default": "./lib/index.js"
28
+ },
29
+ "./client": {
30
+ "types": "./lib/types/client/index.d.ts",
31
+ "default": "./lib/client.js"
32
+ },
33
+ "./cordis.patch.yml": "./cordis.patch.yml",
34
+ "./package.json": "./package.json"
35
+ },
36
+ "files": [
37
+ "lib",
38
+ "cordis.patch.yml",
39
+ "README.md",
40
+ "README.en.md",
41
+ "LICENSE"
42
+ ],
43
+ "engines": {
44
+ "node": ">=20"
45
+ },
46
+ "scripts": {
47
+ "build": "tsc -p tsconfig.json && tsc -p tsconfig.client.json && node scripts/build-client.mjs",
48
+ "prepublishOnly": "pnpm build",
49
+ "prepare": "tsc -p tsconfig.json && tsc -p tsconfig.client.json && node scripts/build-client.mjs",
50
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.public.json"
51
+ },
52
+ "license": "MIT",
53
+ "dsh": {
54
+ "bundle": {
55
+ "patch": "./cordis.patch.yml"
56
+ },
57
+ "client": {
58
+ "inject": [
59
+ "@deepseek-ai/dsh-client-locale",
60
+ "@deepseek-ai/dsh-client-ui-renderer",
61
+ "@deepseek-ai/dsh-client-ui-session",
62
+ "@deepseek-ai/dsh-client-ui-settings",
63
+ "@deepseek-ai/dsh-client-ui-slots"
64
+ ],
65
+ "platform": "web"
66
+ }
67
+ },
68
+ "peerDependencies": {
69
+ "@deepseek-ai/cordis": "^4.0.2",
70
+ "@deepseek-ai/dsh-client-locale": "^0.1.2-alpha.5",
71
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-alpha.5",
72
+ "@deepseek-ai/dsh-client-ui-session": "^0.1.2-alpha.5",
73
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-alpha.5",
74
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.5",
75
+ "@deepseek-ai/dsh-host-webserver": "^0.1.2-alpha.5",
76
+ "@deepseek-ai/dsh-settings": "^0.1.2-alpha.5",
77
+ "@deepseek-ai/schemastery": "^3.18.2",
78
+ "react": "^18.2.0",
79
+ "react-dom": "^18.2.0"
80
+ },
81
+ "peerDependenciesMeta": {
82
+ "cordis": {
83
+ "optional": true
84
+ }
85
+ },
86
+ "devDependencies": {
87
+ "@deepseek-ai/cordis": "^4.0.2",
88
+ "@deepseek-ai/dsh-client-locale": "0.1.2-alpha.5",
89
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.2-alpha.5",
90
+ "@deepseek-ai/dsh-client-ui-session": "0.1.2-alpha.5",
91
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.2-alpha.5",
92
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.2-alpha.5",
93
+ "@deepseek-ai/dsh-host-webserver": "0.1.2-alpha.5",
94
+ "@deepseek-ai/dsh-settings": "0.1.2-alpha.5",
95
+ "@deepseek-ai/schemastery": "^3.18.2",
96
+ "@types/node": "^24.0.0",
97
+ "@types/react": "~18.3.1",
98
+ "@types/react-dom": "~18.3.1",
99
+ "react": "^18.2.0",
100
+ "react-dom": "^18.2.0",
101
+ "typescript": "^5.7.0"
102
+ },
103
+ "dependencies": {}
104
+ }