dsh-patch-edit-plus 0.2.5 → 0.2.7

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,135 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * dsh-patch-edit-plus — 浏览器 half(0.1.7 线;自 0.2.0 线移植)。
4
+ *
5
+ * 单一职责:在 Plugins 页 bundle 详情页的 `plugins.bundle.config` 席位
6
+ * (key = 包名)下注册一张配置卡,暴露两个补丁风格开关——
7
+ * - `allowUnifiedDiff`(Git/unified diff,默认开)
8
+ * - `allowCodexPatch`(Codex apply_patch,默认开——本线两语法皆默认开启)
9
+ *
10
+ * 字段全部是 host 侧 `Config` 的 `.volatile()` 字段:卡片经
11
+ * `configForms.get('dsh-patch-edit-plus')` 自绑本插件 entry(entry id 与
12
+ * 包名一致,无错位),写入走 `form.set(field, !cur)`,提交后宿主经
13
+ * `loader/volatile-update` 原地重注册工具(见 src/index.ts 的 rejudge)。
14
+ *
15
+ * 构建:tsdown → lib/client.js(__ModuleLoader__.load 闭包工厂,id = 包名)。
16
+ * react 是唯一 value-import(平台 external);slots/configForms 经 cordis
17
+ * 服务消费,configForms 缺席时(理论上仅剩极老宿主)卡片整卡隐藏,不阻塞
18
+ * 客户端半。文案内联双语字典(zh/en),不建 locale 文件。
19
+ */
20
+ import { createElement, useSyncExternalStore } from 'react';
21
+ /** 客户端所需服务:slots(席位注册)+ configForms(entry 配置读写)。同族插件
22
+ * (session-guard/perm-gate)同样显式声明——runner 只把声明了的服务提供给模块
23
+ * 上下文,不声明时 `ctx.get('configForms')` 恒为 undefined,卡会渲染成 null。 */
24
+ export const inject = ['slots', 'configForms'];
25
+ /** 内联双语字典(zh/en;按 document.documentElement.lang → navigator.language 兜底)。 */
26
+ const STRINGS = {
27
+ zh: {
28
+ cardName: '补丁风格',
29
+ cardDesc: 'apply_patch 接受的补丁语法',
30
+ unifiedTitle: 'Git 风格补丁',
31
+ unifiedDesc: '接受 Git/unified diff 补丁语法(默认开)',
32
+ codexTitle: 'Codex 风格补丁',
33
+ codexDesc: '接受 Codex apply_patch 语法(默认开)',
34
+ readonlyHint: '当前只读,无法修改。',
35
+ },
36
+ en: {
37
+ cardName: 'Patch style',
38
+ cardDesc: 'Patch syntax accepted by apply_patch',
39
+ unifiedTitle: 'Git-style patches',
40
+ unifiedDesc: 'Accept Git/unified diff patch syntax (default on)',
41
+ codexTitle: 'Codex-style patches',
42
+ codexDesc: 'Accept Codex apply_patch syntax (default on)',
43
+ readonlyHint: 'Read-only right now; changes are not allowed.',
44
+ },
45
+ };
46
+ /** 解析当前语言:document.documentElement.lang 优先,navigator.language 兜底,再退 zh。 */
47
+ function pickLang() {
48
+ try {
49
+ const docLang = typeof document !== 'undefined' ? document.documentElement.lang : '';
50
+ const navLang = typeof navigator !== 'undefined' ? navigator.language : '';
51
+ for (const tag of [docLang, navLang]) {
52
+ if (typeof tag === 'string' && /^zh/i.test(tag))
53
+ return 'zh';
54
+ if (typeof tag === 'string' && /^en/i.test(tag))
55
+ return 'en';
56
+ }
57
+ }
58
+ catch {
59
+ // 非 DOM 环境保底 zh
60
+ }
61
+ return 'zh';
62
+ }
63
+ /** 卡片样式,注入一次(保持 bundle CSS-free;变量与 session-guard 卡同源)。 */
64
+ const CARD_CSS = `
65
+ .ppeCard{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:4px 16px 8px}
66
+ .ppeCardName{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4;margin:10px 0 2px}
67
+ .ppeCardDesc{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5;margin:0 0 4px}
68
+ .ppeRow{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:14px 0;display:flex}
69
+ .ppeRow:last-of-type{border-bottom:0}
70
+ .ppeRowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:48px;display:flex}
71
+ .ppeTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}
72
+ .ppeDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}
73
+ .ppeSwitch{appearance:none;position:relative;width:40px;height:22px;flex:none;cursor:pointer;background:transparent;border:0;padding:0}
74
+ .ppeSwitch:disabled{cursor:not-allowed}
75
+ .ppeSwitchTrack{position:absolute;inset:0;border-radius:22px;background:var(--dsw-alias-interactive-bg-hover);transition:background .16s}
76
+ .ppeSwitch-on>.ppeSwitchTrack{background:var(--dsw-alias-button-primary-fill)}
77
+ .ppeSwitchThumb{position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform .16s}
78
+ .ppeSwitch-on>.ppeSwitchThumb{transform:translateX(18px)}
79
+ .ppeSwitch:disabled>.ppeSwitchTrack{opacity:.5}
80
+ .ppeReadonly{color:var(--dsw-alias-label-tertiary);font-size:12px;margin:8px 0 4px}
81
+ `;
82
+ /** 注入一次卡片样式。 */
83
+ function injectCss() {
84
+ if (typeof document !== 'undefined' && document.querySelector('style[data-plugin-css="patch-edit-plus-card"]') === null) {
85
+ const tag = document.createElement('style');
86
+ tag.dataset.plugin = 'dsh-patch-edit-plus';
87
+ tag.dataset.pluginCss = 'patch-edit-plus-card';
88
+ tag.textContent = CARD_CSS;
89
+ document.head.appendChild(tag);
90
+ }
91
+ }
92
+ const NOOP_SNAPSHOT = { status: 'unavailable', value: undefined, writable: false };
93
+ const unsubscribeNoop = () => { };
94
+ /** 一行 role="switch" 开关(aria-checked + data-* 便于测试选择器)。 */
95
+ function SwitchRow(props) {
96
+ const { field, title, description, checked, disabled, onToggle } = props;
97
+ return (_jsxs("div", { className: "ppeRow", children: [_jsxs("div", { className: "ppeRowText", children: [_jsx("div", { className: "ppeTitle", children: title }), _jsx("div", { className: "ppeDesc", children: description })] }), _jsxs("button", { type: "button", role: "switch", "aria-checked": checked, "data-plugin": "dsh-patch-edit-plus", "data-field": field, "data-checked": checked ? 'true' : 'false', className: 'ppeSwitch' + (checked ? ' ppeSwitch-on' : ''), disabled: disabled, onClick: () => onToggle(field, checked), children: [_jsx("span", { className: "ppeSwitchTrack" }), _jsx("span", { className: "ppeSwitchThumb" })] })] }));
98
+ }
99
+ /**
100
+ * 插件页配置卡主体:两行补丁风格开关。
101
+ * - status === 'unavailable'(无 configForms / entry 未装配)→ 整卡隐藏(null);
102
+ * - status === 'loading' → 开关禁用;
103
+ * - 仅 snapshot.writable 时可写(写路径 `form.set(field, !cur)`)。
104
+ */
105
+ export function PatchStyleCard(props) {
106
+ const form = props.form;
107
+ const snapshot = useSyncExternalStore(form
108
+ ? (listener) => form.subscribe(listener)
109
+ : () => unsubscribeNoop, () => form?.getSnapshot() ?? NOOP_SNAPSHOT);
110
+ injectCss();
111
+ if (snapshot.status === 'unavailable')
112
+ return null;
113
+ const t = STRINGS[pickLang()];
114
+ // loading / 只读都归约为「不可写」:开关禁用,仅 ready + writable 时可写。
115
+ const editable = snapshot.status === 'ready' && snapshot.writable;
116
+ const value = snapshot.value ?? {};
117
+ const toggle = (field, current) => {
118
+ if (form === undefined || !editable)
119
+ return;
120
+ void form.set(field, !current).catch(() => { });
121
+ };
122
+ return (_jsxs("section", { className: "ppeCard", "data-plugin": "dsh-patch-edit-plus", children: [_jsx("div", { className: "ppeCardName", children: t.cardName }), _jsx("p", { className: "ppeCardDesc", children: t.cardDesc }), _jsx(SwitchRow, { field: "allowUnifiedDiff", title: t.unifiedTitle, description: t.unifiedDesc, checked: value.allowUnifiedDiff ?? true, disabled: !editable, onToggle: toggle }), _jsx(SwitchRow, { field: "allowCodexPatch", title: t.codexTitle, description: t.codexDesc, checked: value.allowCodexPatch ?? true, disabled: !editable, onToggle: toggle }), snapshot.status === 'ready' && !snapshot.writable && _jsx("p", { className: "ppeReadonly", children: t.readonlyHint })] }));
123
+ }
124
+ /**
125
+ * 客户端插件体:在 Plugins 页 bundle 详情页的 keyed 席位(key = 包名)下
126
+ * 注册配置卡。卡片自绑 `configForms.get('dsh-patch-edit-plus')`——form 在
127
+ * 渲染期解析(而非 apply 期固化),宿主晚于客户端半开始服务该 entry 时
128
+ * 也能追上;页面注入的 owner props(`{ view: 'page', form }`)不消费,
129
+ * 以本插件 entry 的作用域为唯一事实来源。
130
+ */
131
+ export function apply(ctx) {
132
+ const configForms = (ctx.configForms
133
+ ?? (typeof ctx.get === 'function' ? ctx.get('configForms') : undefined));
134
+ ctx.slots.inject('plugins.bundle.config', () => ctx.slots.register({ name: 'plugins.bundle.config', key: 'dsh-patch-edit-plus' }, () => createElement(PatchStyleCard, { form: configForms?.get?.('dsh-patch-edit-plus') })));
135
+ }
package/lib/client.js ADDED
@@ -0,0 +1,203 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "dsh-patch-edit-plus",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+ let react = require("react");
8
+ let react_jsx_runtime = require("react/jsx-runtime");
9
+ //#region src/client/index.tsx
10
+ /**
11
+ * dsh-patch-edit-plus — 浏览器 half(0.1.7 线;自 0.2.0 线移植)。
12
+ *
13
+ * 单一职责:在 Plugins 页 bundle 详情页的 `plugins.bundle.config` 席位
14
+ * (key = 包名)下注册一张配置卡,暴露两个补丁风格开关——
15
+ * - `allowUnifiedDiff`(Git/unified diff,默认开)
16
+ * - `allowCodexPatch`(Codex apply_patch,默认开——本线两语法皆默认开启)
17
+ *
18
+ * 字段全部是 host 侧 `Config` 的 `.volatile()` 字段:卡片经
19
+ * `configForms.get('dsh-patch-edit-plus')` 自绑本插件 entry(entry id 与
20
+ * 包名一致,无错位),写入走 `form.set(field, !cur)`,提交后宿主经
21
+ * `loader/volatile-update` 原地重注册工具(见 src/index.ts 的 rejudge)。
22
+ *
23
+ * 构建:tsdown → lib/client.js(__ModuleLoader__.load 闭包工厂,id = 包名)。
24
+ * react 是唯一 value-import(平台 external);slots/configForms 经 cordis
25
+ * 服务消费,configForms 缺席时(理论上仅剩极老宿主)卡片整卡隐藏,不阻塞
26
+ * 客户端半。文案内联双语字典(zh/en),不建 locale 文件。
27
+ */
28
+ /** 客户端所需服务:slots(席位注册)+ configForms(entry 配置读写)。同族插件
29
+ * (session-guard/perm-gate)同样显式声明——runner 只把声明了的服务提供给模块
30
+ * 上下文,不声明时 `ctx.get('configForms')` 恒为 undefined,卡会渲染成 null。 */
31
+ const inject = ["slots", "configForms"];
32
+ /** 内联双语字典(zh/en;按 document.documentElement.lang → navigator.language 兜底)。 */
33
+ const STRINGS = {
34
+ zh: {
35
+ cardName: "补丁风格",
36
+ cardDesc: "apply_patch 接受的补丁语法",
37
+ unifiedTitle: "Git 风格补丁",
38
+ unifiedDesc: "接受 Git/unified diff 补丁语法(默认开)",
39
+ codexTitle: "Codex 风格补丁",
40
+ codexDesc: "接受 Codex apply_patch 语法(默认开)",
41
+ readonlyHint: "当前只读,无法修改。"
42
+ },
43
+ en: {
44
+ cardName: "Patch style",
45
+ cardDesc: "Patch syntax accepted by apply_patch",
46
+ unifiedTitle: "Git-style patches",
47
+ unifiedDesc: "Accept Git/unified diff patch syntax (default on)",
48
+ codexTitle: "Codex-style patches",
49
+ codexDesc: "Accept Codex apply_patch syntax (default on)",
50
+ readonlyHint: "Read-only right now; changes are not allowed."
51
+ }
52
+ };
53
+ /** 解析当前语言:document.documentElement.lang 优先,navigator.language 兜底,再退 zh。 */
54
+ function pickLang() {
55
+ try {
56
+ const docLang = typeof document !== "undefined" ? document.documentElement.lang : "";
57
+ const navLang = typeof navigator !== "undefined" ? navigator.language : "";
58
+ for (const tag of [docLang, navLang]) {
59
+ if (typeof tag === "string" && /^zh/i.test(tag)) return "zh";
60
+ if (typeof tag === "string" && /^en/i.test(tag)) return "en";
61
+ }
62
+ } catch {}
63
+ return "zh";
64
+ }
65
+ /** 卡片样式,注入一次(保持 bundle CSS-free;变量与 session-guard 卡同源)。 */
66
+ const CARD_CSS = `
67
+ .ppeCard{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:4px 16px 8px}
68
+ .ppeCardName{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4;margin:10px 0 2px}
69
+ .ppeCardDesc{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5;margin:0 0 4px}
70
+ .ppeRow{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:14px 0;display:flex}
71
+ .ppeRow:last-of-type{border-bottom:0}
72
+ .ppeRowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:48px;display:flex}
73
+ .ppeTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}
74
+ .ppeDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}
75
+ .ppeSwitch{appearance:none;position:relative;width:40px;height:22px;flex:none;cursor:pointer;background:transparent;border:0;padding:0}
76
+ .ppeSwitch:disabled{cursor:not-allowed}
77
+ .ppeSwitchTrack{position:absolute;inset:0;border-radius:22px;background:var(--dsw-alias-interactive-bg-hover);transition:background .16s}
78
+ .ppeSwitch-on>.ppeSwitchTrack{background:var(--dsw-alias-button-primary-fill)}
79
+ .ppeSwitchThumb{position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform .16s}
80
+ .ppeSwitch-on>.ppeSwitchThumb{transform:translateX(18px)}
81
+ .ppeSwitch:disabled>.ppeSwitchTrack{opacity:.5}
82
+ .ppeReadonly{color:var(--dsw-alias-label-tertiary);font-size:12px;margin:8px 0 4px}
83
+ `;
84
+ /** 注入一次卡片样式。 */
85
+ function injectCss() {
86
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"patch-edit-plus-card\"]") === null) {
87
+ const tag = document.createElement("style");
88
+ tag.dataset.plugin = "dsh-patch-edit-plus";
89
+ tag.dataset.pluginCss = "patch-edit-plus-card";
90
+ tag.textContent = CARD_CSS;
91
+ document.head.appendChild(tag);
92
+ }
93
+ }
94
+ const NOOP_SNAPSHOT = {
95
+ status: "unavailable",
96
+ value: void 0,
97
+ writable: false
98
+ };
99
+ const unsubscribeNoop = () => {};
100
+ /** 一行 role="switch" 开关(aria-checked + data-* 便于测试选择器)。 */
101
+ function SwitchRow(props) {
102
+ const { field, title, description, checked, disabled, onToggle } = props;
103
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
104
+ className: "ppeRow",
105
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
106
+ className: "ppeRowText",
107
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
108
+ className: "ppeTitle",
109
+ children: title
110
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
111
+ className: "ppeDesc",
112
+ children: description
113
+ })]
114
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
115
+ type: "button",
116
+ role: "switch",
117
+ "aria-checked": checked,
118
+ "data-plugin": "dsh-patch-edit-plus",
119
+ "data-field": field,
120
+ "data-checked": checked ? "true" : "false",
121
+ className: "ppeSwitch" + (checked ? " ppeSwitch-on" : ""),
122
+ disabled,
123
+ onClick: () => onToggle(field, checked),
124
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "ppeSwitchTrack" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "ppeSwitchThumb" })]
125
+ })]
126
+ });
127
+ }
128
+ /**
129
+ * 插件页配置卡主体:两行补丁风格开关。
130
+ * - status === 'unavailable'(无 configForms / entry 未装配)→ 整卡隐藏(null);
131
+ * - status === 'loading' → 开关禁用;
132
+ * - 仅 snapshot.writable 时可写(写路径 `form.set(field, !cur)`)。
133
+ */
134
+ function PatchStyleCard(props) {
135
+ const form = props.form;
136
+ const snapshot = (0, react.useSyncExternalStore)(form ? (listener) => form.subscribe(listener) : () => unsubscribeNoop, () => form?.getSnapshot() ?? NOOP_SNAPSHOT);
137
+ injectCss();
138
+ if (snapshot.status === "unavailable") return null;
139
+ const t = STRINGS[pickLang()];
140
+ const editable = snapshot.status === "ready" && snapshot.writable;
141
+ const value = snapshot.value ?? {};
142
+ const toggle = (field, current) => {
143
+ if (form === void 0 || !editable) return;
144
+ form.set(field, !current).catch(() => {});
145
+ };
146
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
147
+ className: "ppeCard",
148
+ "data-plugin": "dsh-patch-edit-plus",
149
+ children: [
150
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
151
+ className: "ppeCardName",
152
+ children: t.cardName
153
+ }),
154
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
155
+ className: "ppeCardDesc",
156
+ children: t.cardDesc
157
+ }),
158
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SwitchRow, {
159
+ field: "allowUnifiedDiff",
160
+ title: t.unifiedTitle,
161
+ description: t.unifiedDesc,
162
+ checked: value.allowUnifiedDiff ?? true,
163
+ disabled: !editable,
164
+ onToggle: toggle
165
+ }),
166
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SwitchRow, {
167
+ field: "allowCodexPatch",
168
+ title: t.codexTitle,
169
+ description: t.codexDesc,
170
+ checked: value.allowCodexPatch ?? true,
171
+ disabled: !editable,
172
+ onToggle: toggle
173
+ }),
174
+ snapshot.status === "ready" && !snapshot.writable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
175
+ className: "ppeReadonly",
176
+ children: t.readonlyHint
177
+ })
178
+ ]
179
+ });
180
+ }
181
+ /**
182
+ * 客户端插件体:在 Plugins 页 bundle 详情页的 keyed 席位(key = 包名)下
183
+ * 注册配置卡。卡片自绑 `configForms.get('dsh-patch-edit-plus')`——form 在
184
+ * 渲染期解析(而非 apply 期固化),宿主晚于客户端半开始服务该 entry 时
185
+ * 也能追上;页面注入的 owner props(`{ view: 'page', form }`)不消费,
186
+ * 以本插件 entry 的作用域为唯一事实来源。
187
+ */
188
+ function apply(ctx) {
189
+ const configForms = ctx.configForms ?? (typeof ctx.get === "function" ? ctx.get("configForms") : void 0);
190
+ ctx.slots.inject("plugins.bundle.config", () => ctx.slots.register({
191
+ name: "plugins.bundle.config",
192
+ key: "dsh-patch-edit-plus"
193
+ }, () => (0, react.createElement)(PatchStyleCard, { form: configForms?.get?.("dsh-patch-edit-plus") })));
194
+ }
195
+ //#endregion
196
+ exports.PatchStyleCard = PatchStyleCard;
197
+ exports.apply = apply;
198
+ exports.inject = inject;
199
+ return module.exports;
200
+ }
201
+ });
202
+
203
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","names":["useSyncExternalStore","createElement"],"sources":["../src/client/index.tsx"],"sourcesContent":["/**\n * dsh-patch-edit-plus — 浏览器 half(0.1.7 线;自 0.2.0 线移植)。\n *\n * 单一职责:在 Plugins 页 bundle 详情页的 `plugins.bundle.config` 席位\n * (key = 包名)下注册一张配置卡,暴露两个补丁风格开关——\n * - `allowUnifiedDiff`(Git/unified diff,默认开)\n * - `allowCodexPatch`(Codex apply_patch,默认开——本线两语法皆默认开启)\n *\n * 字段全部是 host 侧 `Config` 的 `.volatile()` 字段:卡片经\n * `configForms.get('dsh-patch-edit-plus')` 自绑本插件 entry(entry id 与\n * 包名一致,无错位),写入走 `form.set(field, !cur)`,提交后宿主经\n * `loader/volatile-update` 原地重注册工具(见 src/index.ts 的 rejudge)。\n *\n * 构建:tsdown → lib/client.js(__ModuleLoader__.load 闭包工厂,id = 包名)。\n * react 是唯一 value-import(平台 external);slots/configForms 经 cordis\n * 服务消费,configForms 缺席时(理论上仅剩极老宿主)卡片整卡隐藏,不阻塞\n * 客户端半。文案内联双语字典(zh/en),不建 locale 文件。\n */\nimport { createElement, useSyncExternalStore } from 'react'\nimport type { JSX } from 'react'\n\n/** 本插件消费的 configForms 值形状(与 host ResolvedConfig 的易变布尔对齐)。 */\nexport interface PatchEditPlusConfig {\n allowUnifiedDiff: boolean\n allowCodexPatch: boolean\n}\n\n/** configForms 作用域面(结构性子集;0.1.7+ 缝,避免硬 peer 类型)。 */\nexport interface PatchFormScope {\n getSnapshot(): {\n status: 'loading' | 'ready' | 'unavailable'\n value: Partial<PatchEditPlusConfig> | undefined\n writable: boolean\n }\n subscribe(listener: () => void): () => void\n set(field: string, value: unknown): Promise<boolean>\n}\n\n/** configForms 服务面(以 entry id 取句柄)。 */\ninterface ConfigFormsFace {\n get?(entryId: string): PatchFormScope | undefined\n}\n\n/** 客户端所需服务:slots(席位注册)+ configForms(entry 配置读写)。同族插件\n * (session-guard/perm-gate)同样显式声明——runner 只把声明了的服务提供给模块\n * 上下文,不声明时 `ctx.get('configForms')` 恒为 undefined,卡会渲染成 null。 */\nexport const inject = ['slots', 'configForms']\n\n/** 轻量 ctx 类型(仅本客户端用到的方法;构建时类型被剥离)。 */\ninterface SlotsFace {\n inject: (_name: string, _fn: () => unknown) => () => void\n register: (_options: Record<string, unknown>, _component: unknown) => () => void\n}\ninterface ClientCtx {\n slots: SlotsFace\n get?: (_name: string) => unknown\n}\n\n/** 内联双语字典(zh/en;按 document.documentElement.lang → navigator.language 兜底)。 */\nconst STRINGS = {\n zh: {\n cardName: '补丁风格',\n cardDesc: 'apply_patch 接受的补丁语法',\n unifiedTitle: 'Git 风格补丁',\n unifiedDesc: '接受 Git/unified diff 补丁语法(默认开)',\n codexTitle: 'Codex 风格补丁',\n codexDesc: '接受 Codex apply_patch 语法(默认开)',\n readonlyHint: '当前只读,无法修改。',\n },\n en: {\n cardName: 'Patch style',\n cardDesc: 'Patch syntax accepted by apply_patch',\n unifiedTitle: 'Git-style patches',\n unifiedDesc: 'Accept Git/unified diff patch syntax (default on)',\n codexTitle: 'Codex-style patches',\n codexDesc: 'Accept Codex apply_patch syntax (default on)',\n readonlyHint: 'Read-only right now; changes are not allowed.',\n },\n} as const\n\ntype Lang = keyof typeof STRINGS\n\n/** 解析当前语言:document.documentElement.lang 优先,navigator.language 兜底,再退 zh。 */\nfunction pickLang(): Lang {\n try {\n const docLang = typeof document !== 'undefined' ? document.documentElement.lang : ''\n const navLang = typeof navigator !== 'undefined' ? navigator.language : ''\n for (const tag of [docLang, navLang]) {\n if (typeof tag === 'string' && /^zh/i.test(tag)) return 'zh'\n if (typeof tag === 'string' && /^en/i.test(tag)) return 'en'\n }\n } catch {\n // 非 DOM 环境保底 zh\n }\n return 'zh'\n}\n\n/** 卡片样式,注入一次(保持 bundle CSS-free;变量与 session-guard 卡同源)。 */\nconst CARD_CSS = `\n.ppeCard{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:4px 16px 8px}\n.ppeCardName{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4;margin:10px 0 2px}\n.ppeCardDesc{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5;margin:0 0 4px}\n.ppeRow{border-bottom:1px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;padding:14px 0;display:flex}\n.ppeRow:last-of-type{border-bottom:0}\n.ppeRowText{flex-direction:column;flex:1;gap:4px;min-width:0;padding-right:48px;display:flex}\n.ppeTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:400;line-height:22px}\n.ppeDesc{color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:400;line-height:18px}\n.ppeSwitch{appearance:none;position:relative;width:40px;height:22px;flex:none;cursor:pointer;background:transparent;border:0;padding:0}\n.ppeSwitch:disabled{cursor:not-allowed}\n.ppeSwitchTrack{position:absolute;inset:0;border-radius:22px;background:var(--dsw-alias-interactive-bg-hover);transition:background .16s}\n.ppeSwitch-on>.ppeSwitchTrack{background:var(--dsw-alias-button-primary-fill)}\n.ppeSwitchThumb{position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform .16s}\n.ppeSwitch-on>.ppeSwitchThumb{transform:translateX(18px)}\n.ppeSwitch:disabled>.ppeSwitchTrack{opacity:.5}\n.ppeReadonly{color:var(--dsw-alias-label-tertiary);font-size:12px;margin:8px 0 4px}\n`\n\n/** 注入一次卡片样式。 */\nfunction injectCss(): void {\n if (typeof document !== 'undefined' && document.querySelector('style[data-plugin-css=\"patch-edit-plus-card\"]') === null) {\n const tag = document.createElement('style')\n tag.dataset.plugin = 'dsh-patch-edit-plus'\n tag.dataset.pluginCss = 'patch-edit-plus-card'\n tag.textContent = CARD_CSS\n document.head.appendChild(tag)\n }\n}\n\nconst NOOP_SNAPSHOT = { status: 'unavailable' as const, value: undefined, writable: false }\nconst unsubscribeNoop = (): void => {}\n\n/** 一行 role=\"switch\" 开关(aria-checked + data-* 便于测试选择器)。 */\nfunction SwitchRow(props: {\n field: 'allowUnifiedDiff' | 'allowCodexPatch'\n title: string\n description: string\n checked: boolean\n disabled: boolean\n onToggle: (_field: 'allowUnifiedDiff' | 'allowCodexPatch', _current: boolean) => void\n}): JSX.Element {\n const { field, title, description, checked, disabled, onToggle } = props\n return (\n <div className=\"ppeRow\">\n <div className=\"ppeRowText\">\n <div className=\"ppeTitle\">{title}</div>\n <div className=\"ppeDesc\">{description}</div>\n </div>\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n data-plugin=\"dsh-patch-edit-plus\"\n data-field={field}\n data-checked={checked ? 'true' : 'false'}\n className={'ppeSwitch' + (checked ? ' ppeSwitch-on' : '')}\n disabled={disabled}\n onClick={() => onToggle(field, checked)}\n >\n <span className=\"ppeSwitchTrack\" />\n <span className=\"ppeSwitchThumb\" />\n </button>\n </div>\n )\n}\n\n/**\n * 插件页配置卡主体:两行补丁风格开关。\n * - status === 'unavailable'(无 configForms / entry 未装配)→ 整卡隐藏(null);\n * - status === 'loading' → 开关禁用;\n * - 仅 snapshot.writable 时可写(写路径 `form.set(field, !cur)`)。\n */\nexport function PatchStyleCard(props: { form?: PatchFormScope | undefined }): JSX.Element | null {\n const form = props.form\n const snapshot = useSyncExternalStore(\n form\n ? (listener) => form.subscribe(listener)\n : () => unsubscribeNoop,\n () => form?.getSnapshot() ?? NOOP_SNAPSHOT,\n )\n\n injectCss()\n\n if (snapshot.status === 'unavailable') return null\n const t = STRINGS[pickLang()]\n // loading / 只读都归约为「不可写」:开关禁用,仅 ready + writable 时可写。\n const editable = snapshot.status === 'ready' && snapshot.writable\n const value = snapshot.value ?? {}\n const toggle = (field: 'allowUnifiedDiff' | 'allowCodexPatch', current: boolean): void => {\n if (form === undefined || !editable) return\n void form.set(field, !current).catch(() => {})\n }\n return (\n <section className=\"ppeCard\" data-plugin=\"dsh-patch-edit-plus\">\n <div className=\"ppeCardName\">{t.cardName}</div>\n <p className=\"ppeCardDesc\">{t.cardDesc}</p>\n <SwitchRow\n field=\"allowUnifiedDiff\"\n title={t.unifiedTitle}\n description={t.unifiedDesc}\n checked={value.allowUnifiedDiff ?? true}\n disabled={!editable}\n onToggle={toggle}\n />\n <SwitchRow\n field=\"allowCodexPatch\"\n title={t.codexTitle}\n description={t.codexDesc}\n checked={value.allowCodexPatch ?? true}\n disabled={!editable}\n onToggle={toggle}\n />\n {snapshot.status === 'ready' && !snapshot.writable && <p className=\"ppeReadonly\">{t.readonlyHint}</p>}\n </section>\n )\n}\n\n/**\n * 客户端插件体:在 Plugins 页 bundle 详情页的 keyed 席位(key = 包名)下\n * 注册配置卡。卡片自绑 `configForms.get('dsh-patch-edit-plus')`——form 在\n * 渲染期解析(而非 apply 期固化),宿主晚于客户端半开始服务该 entry 时\n * 也能追上;页面注入的 owner props(`{ view: 'page', form }`)不消费,\n * 以本插件 entry 的作用域为唯一事实来源。\n */\nexport function apply(ctx: ClientCtx): void {\n const configForms = ((ctx as unknown as { configForms?: ConfigFormsFace }).configForms\n ?? (typeof ctx.get === 'function' ? ctx.get('configForms') : undefined)) as ConfigFormsFace | undefined\n ctx.slots.inject('plugins.bundle.config', () => ctx.slots.register(\n { name: 'plugins.bundle.config', key: 'dsh-patch-edit-plus' },\n () => createElement(PatchStyleCard, { form: configForms?.get?.('dsh-patch-edit-plus') }),\n ))\n}\n"],"mappings":"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"}
package/lib/config.js CHANGED
@@ -11,7 +11,7 @@ export const Config = z.object({
11
11
  toolName: z.string().default('apply_patch'),
12
12
  conflictPolicy: z.union(['rename', 'skip', 'fail']).default('rename'),
13
13
  renameSuffix: z.string().default('_1'),
14
- allowUnifiedDiff: z.boolean().default(true),
14
+ allowUnifiedDiff: z.boolean().default(true).volatile(),
15
15
  allowCodexPatch: z.boolean().default(true).volatile(),
16
16
  deleteBackend: z.union(['shell', 'none']).default('shell'),
17
17
  shellDialect: z.union(['auto', 'posix', 'pwsh']).default('auto'),
@@ -38,7 +38,7 @@ export function resolveConfig(config) {
38
38
  toolName: typeof c.toolName === 'string' && c.toolName.trim() !== '' ? c.toolName : 'apply_patch',
39
39
  conflictPolicy: c.conflictPolicy ?? 'rename',
40
40
  renameSuffix: typeof c.renameSuffix === 'string' ? c.renameSuffix : '_1',
41
- allowUnifiedDiff: c.allowUnifiedDiff ?? true,
41
+ allowUnifiedDiff: readVolatileBoolean(c.allowUnifiedDiff, true),
42
42
  allowCodexPatch: readVolatileBoolean(c.allowCodexPatch, true),
43
43
  deleteBackend: c.deleteBackend ?? 'shell',
44
44
  shellDialect: c.shellDialect ?? 'auto',
@@ -0,0 +1,47 @@
1
+ import type { JSX } from 'react';
2
+ /** 本插件消费的 configForms 值形状(与 host ResolvedConfig 的易变布尔对齐)。 */
3
+ export interface PatchEditPlusConfig {
4
+ allowUnifiedDiff: boolean;
5
+ allowCodexPatch: boolean;
6
+ }
7
+ /** configForms 作用域面(结构性子集;0.1.7+ 缝,避免硬 peer 类型)。 */
8
+ export interface PatchFormScope {
9
+ getSnapshot(): {
10
+ status: 'loading' | 'ready' | 'unavailable';
11
+ value: Partial<PatchEditPlusConfig> | undefined;
12
+ writable: boolean;
13
+ };
14
+ subscribe(listener: () => void): () => void;
15
+ set(field: string, value: unknown): Promise<boolean>;
16
+ }
17
+ /** 客户端所需服务:slots(席位注册)+ configForms(entry 配置读写)。同族插件
18
+ * (session-guard/perm-gate)同样显式声明——runner 只把声明了的服务提供给模块
19
+ * 上下文,不声明时 `ctx.get('configForms')` 恒为 undefined,卡会渲染成 null。 */
20
+ export declare const inject: string[];
21
+ /** 轻量 ctx 类型(仅本客户端用到的方法;构建时类型被剥离)。 */
22
+ interface SlotsFace {
23
+ inject: (_name: string, _fn: () => unknown) => () => void;
24
+ register: (_options: Record<string, unknown>, _component: unknown) => () => void;
25
+ }
26
+ interface ClientCtx {
27
+ slots: SlotsFace;
28
+ get?: (_name: string) => unknown;
29
+ }
30
+ /**
31
+ * 插件页配置卡主体:两行补丁风格开关。
32
+ * - status === 'unavailable'(无 configForms / entry 未装配)→ 整卡隐藏(null);
33
+ * - status === 'loading' → 开关禁用;
34
+ * - 仅 snapshot.writable 时可写(写路径 `form.set(field, !cur)`)。
35
+ */
36
+ export declare function PatchStyleCard(props: {
37
+ form?: PatchFormScope | undefined;
38
+ }): JSX.Element | null;
39
+ /**
40
+ * 客户端插件体:在 Plugins 页 bundle 详情页的 keyed 席位(key = 包名)下
41
+ * 注册配置卡。卡片自绑 `configForms.get('dsh-patch-edit-plus')`——form 在
42
+ * 渲染期解析(而非 apply 期固化),宿主晚于客户端半开始服务该 entry 时
43
+ * 也能追上;页面注入的 owner props(`{ view: 'page', form }`)不消费,
44
+ * 以本插件 entry 的作用域为唯一事实来源。
45
+ */
46
+ export declare function apply(ctx: ClientCtx): void;
47
+ export {};
@@ -21,8 +21,10 @@ export interface Config {
21
21
  conflictPolicy?: ConflictPolicy;
22
22
  /** Suffix appended on rename avoidance. Defaults to `_1`. */
23
23
  renameSuffix?: string;
24
- /** Accept git/unified diff patches. Defaults to true. */
25
- allowUnifiedDiff?: boolean;
24
+ /** Accept git/unified diff patches. Defaults to true.
25
+ * 0.1.7 `.volatile()`: the loader hands `apply` a live `Volatile` ref for this
26
+ * field — always read it through `readVolatileBoolean`, never cache the ref. */
27
+ allowUnifiedDiff?: boolean | Volatile<boolean>;
26
28
  /** Accept Codex `apply_patch` syntax. Defaults to true (both syntaxes on;
27
29
  * the patch-layer row in `cordis.patch.yml` carries the same default). Set
28
30
  * false to restore unified-diff-only.
@@ -53,7 +55,7 @@ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
53
55
  toolName: z<string, string, "defined">;
54
56
  conflictPolicy: z<"rename" | "skip" | "fail", "rename" | "skip" | "fail", "defined">;
55
57
  renameSuffix: z<string, string, "defined">;
56
- allowUnifiedDiff: z<boolean, boolean, "defined">;
58
+ allowUnifiedDiff: z<boolean, boolean, "volatile-defined">;
57
59
  allowCodexPatch: z<boolean, boolean, "volatile-defined">;
58
60
  deleteBackend: z<"shell" | "none", "shell" | "none", "defined">;
59
61
  shellDialect: z<"auto" | "posix" | "pwsh", "auto" | "posix" | "pwsh", "defined">;
@@ -68,7 +70,7 @@ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
68
70
  toolName: z<string, string, "defined">;
69
71
  conflictPolicy: z<"rename" | "skip" | "fail", "rename" | "skip" | "fail", "defined">;
70
72
  renameSuffix: z<string, string, "defined">;
71
- allowUnifiedDiff: z<boolean, boolean, "defined">;
73
+ allowUnifiedDiff: z<boolean, boolean, "volatile-defined">;
72
74
  allowCodexPatch: z<boolean, boolean, "volatile-defined">;
73
75
  deleteBackend: z<"shell" | "none", "shell" | "none", "defined">;
74
76
  shellDialect: z<"auto" | "posix" | "pwsh", "auto" | "posix" | "pwsh", "defined">;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-patch-edit-plus",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Patch-style file editing for DeepSeek Harness: one apply_patch tool accepting git/unified diff and Codex apply_patch syntax (both enabled by default), with all-or-nothing application, read-before-write intent dance, sandbox-aware delete/move, with a DSH 0.1.7+ line (declarative volatile settings).",
5
5
  "type": "module",
6
6
  "repository": {
@@ -14,6 +14,10 @@
14
14
  "types": "./lib/types/index.d.ts",
15
15
  "default": "./lib/index.js"
16
16
  },
17
+ "./client": {
18
+ "types": "./lib/types/client/index.d.ts",
19
+ "default": "./lib/client.js"
20
+ },
17
21
  "./package.json": "./package.json"
18
22
  },
19
23
  "files": [
@@ -31,10 +35,16 @@
31
35
  "dsh": {
32
36
  "bundle": {
33
37
  "patch": "./cordis.patch.yml"
38
+ },
39
+ "client": {
40
+ "platform": "web",
41
+ "inject": [
42
+ "@deepseek-ai/dsh-client-ui-settings"
43
+ ]
34
44
  }
35
45
  },
36
46
  "scripts": {
37
- "build": "tsc -p tsconfig.build.json",
47
+ "build": "tsc -p tsconfig.build.json && tsdown",
38
48
  "prepublishOnly": "npm run build",
39
49
  "typecheck": "tsc -p tsconfig.json",
40
50
  "typecheck:0.1.5": "node scripts/typecheck-0.1.5.mjs",
@@ -62,15 +72,24 @@
62
72
  ],
63
73
  "peerDependencies": {
64
74
  "@deepseek-ai/cordis": "^4.0.1",
75
+ "@deepseek-ai/dsh-client-ui-settings": ">=0.1.7-rc.1 <0.1.8-0",
76
+ "@deepseek-ai/dsh-client-ui-slots": ">=0.1.7-rc.1 <0.1.8-0",
65
77
  "@deepseek-ai/dsh-fs": ">=0.1.7-rc.1 <0.1.8-0",
66
78
  "@deepseek-ai/dsh-sandbox": ">=0.1.7-rc.1 <0.1.8-0",
67
79
  "@deepseek-ai/dsh-shell": ">=0.1.7-rc.1 <0.1.8-0",
68
- "@deepseek-ai/dsh-tools": ">=0.1.7-rc.1 <0.1.8-0"
80
+ "@deepseek-ai/dsh-tools": ">=0.1.7-rc.1 <0.1.8-0",
81
+ "react": "^18.2.0"
69
82
  },
70
83
  "peerDependenciesMeta": {
71
84
  "@deepseek-ai/cordis": {
72
85
  "optional": true
73
86
  },
87
+ "@deepseek-ai/dsh-client-ui-settings": {
88
+ "optional": true
89
+ },
90
+ "@deepseek-ai/dsh-client-ui-slots": {
91
+ "optional": true
92
+ },
74
93
  "@deepseek-ai/dsh-fs": {
75
94
  "optional": true
76
95
  },
@@ -95,7 +114,10 @@
95
114
  "@deepseek-ai/dsh-tools": "0.1.7-rc.2",
96
115
  "@eslint/js": "^9.0.0",
97
116
  "@types/node": "^22.0.0",
117
+ "@types/react": "~18.3.1",
98
118
  "eslint": "^9.0.0",
119
+ "react": "^18.2.0",
120
+ "tsdown": "^0.22.2",
99
121
  "typescript": "^5.6.0",
100
122
  "typescript-eslint": "^8.0.0",
101
123
  "vitest": "^3.0.0",