dsh-prompt-rewriter 1.4.1 → 1.5.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/README.md +1 -0
- package/README.zh.md +1 -0
- package/client.js +45 -7
- package/index.js +54 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -97,6 +97,7 @@ Only images **currently sitting in the composer** — **never images from earlie
|
|
|
97
97
|
- The model dropdown lists **the providers and models you actually have** — you can't type in one that doesn't exist.
|
|
98
98
|
- Turning the model switch off does not clear your selection; flipping it back on shows the same choice.
|
|
99
99
|
- Images still uploading are skipped, and the status area tells you how many were missed. A rewrite never fails because of an image.
|
|
100
|
+
- The **current version** sits in the top-right of the settings page; clicking it opens the project home page. Check it before reporting a problem — it makes the issue much easier to pin down.
|
|
100
101
|
|
|
101
102
|
## Install
|
|
102
103
|
|
package/README.zh.md
CHANGED
package/client.js
CHANGED
|
@@ -111,8 +111,21 @@ window.__ModuleLoader__.load({
|
|
|
111
111
|
// ---- Settings page -------------------------------------------------
|
|
112
112
|
// Host theme tokens only, so the page follows light/dark automatically.
|
|
113
113
|
'.dsh-pe-settings{display:flex;flex-direction:column;gap:4px;max-width:640px}',
|
|
114
|
-
|
|
114
|
+
// Header line: intro on the left, version on the right, the way the plugin
|
|
115
|
+
// market pairs a description with its package version.
|
|
116
|
+
'.dsh-pe-settingsHead{display:flex;flex-wrap:wrap;align-items:baseline;',
|
|
117
|
+
'justify-content:space-between;gap:4px 12px;margin:0 0 8px}',
|
|
118
|
+
'.dsh-pe-settingsIntro{margin:0;color:var(--dsw-alias-label-secondary);',
|
|
115
119
|
'font-size:13px;line-height:20px}',
|
|
120
|
+
// Same weight and colour as the host's own package version labels: muted,
|
|
121
|
+
// monospace, and unobtrusive until hovered.
|
|
122
|
+
'.dsh-pe-version{flex:none;font-size:12px;line-height:20px;color:var(--dsw-alias-label-tertiary);',
|
|
123
|
+
'font-family:var(--dsw-font-mono,ui-monospace,SFMono-Regular,Menlo,monospace);',
|
|
124
|
+
'text-decoration:none;border-radius:var(--dsw-radius-sm)}',
|
|
125
|
+
'a.dsh-pe-version{cursor:pointer}',
|
|
126
|
+
'a.dsh-pe-version:hover{color:var(--dsw-alias-label-secondary);text-decoration:underline}',
|
|
127
|
+
'a.dsh-pe-version:focus-visible{outline:none;color:var(--dsw-alias-label-secondary);',
|
|
128
|
+
'box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary))}',
|
|
116
129
|
// Each row is a two-column flex that WRAPS. Wrapping is what makes the
|
|
117
130
|
// narrow case work: `@container` cannot be used here because the host
|
|
118
131
|
// settings panel owns the ancestor chain and declares no container-type,
|
|
@@ -789,6 +802,9 @@ window.__ModuleLoader__.load({
|
|
|
789
802
|
*/
|
|
790
803
|
function SettingsSection({ t, getRemote }) {
|
|
791
804
|
const [values, setValues] = useState(null);
|
|
805
|
+
// `{ version, url }` reported by the Host from the package manifest. Never
|
|
806
|
+
// hard-coded here: a release only bumps package.json.
|
|
807
|
+
const [about, setAbout] = useState(null);
|
|
792
808
|
const [catalog, setCatalog] = useState({ status: 'loading', groups: [] });
|
|
793
809
|
const [error, setError] = useState(null);
|
|
794
810
|
const [saving, setSaving] = useState(false);
|
|
@@ -854,6 +870,7 @@ window.__ModuleLoader__.load({
|
|
|
854
870
|
if (!alive.current) return;
|
|
855
871
|
if (body?.ok !== true) throw new Error(body?.message || t('settings.loadFailed', { status: response.status }));
|
|
856
872
|
setValues(body.values);
|
|
873
|
+
if (body.about !== undefined) setAbout(body.about);
|
|
857
874
|
} catch (failure) {
|
|
858
875
|
if (alive.current && !controller.signal.aborted) setError(failure instanceof Error ? failure.message : String(failure));
|
|
859
876
|
}
|
|
@@ -929,7 +946,21 @@ window.__ModuleLoader__.load({
|
|
|
929
946
|
return h(
|
|
930
947
|
'div',
|
|
931
948
|
{ className: 'dsh-pe-settings' },
|
|
932
|
-
|
|
949
|
+
// Intro line with the version at the right, the way the plugin market shows a
|
|
950
|
+
// package version beside its description. The version links to the project
|
|
951
|
+
// page and opens in a new tab, so the current session is left untouched.
|
|
952
|
+
h('div', { className: 'dsh-pe-settingsHead' },
|
|
953
|
+
h('p', { className: 'dsh-pe-settingsIntro' }, t('settings.intro')),
|
|
954
|
+
about?.version !== undefined && (about?.url === undefined
|
|
955
|
+
? h('span', { className: 'dsh-pe-version' }, `v${about.version}`)
|
|
956
|
+
: h('a', {
|
|
957
|
+
className: 'dsh-pe-version',
|
|
958
|
+
href: about.url,
|
|
959
|
+
target: '_blank',
|
|
960
|
+
rel: 'noopener noreferrer',
|
|
961
|
+
title: about.url,
|
|
962
|
+
}, `v${about.version}`)),
|
|
963
|
+
),
|
|
933
964
|
|
|
934
965
|
row(
|
|
935
966
|
'model',
|
|
@@ -987,7 +1018,10 @@ window.__ModuleLoader__.load({
|
|
|
987
1018
|
row(
|
|
988
1019
|
'context',
|
|
989
1020
|
t('settings.context.title'),
|
|
990
|
-
|
|
1021
|
+
// The dot's meaning rides along in the same hint, separated by a space,
|
|
1022
|
+
// so the row stays one comfortable block instead of growing a second
|
|
1023
|
+
// paragraph.
|
|
1024
|
+
`${values.referenceContext ? t('settings.context.on') : t('settings.context.off')} ${t('settings.context.mark')}`,
|
|
991
1025
|
toggle('settings.context', values.referenceContext, (next) => save({ referenceContext: next }, 'settings.context')),
|
|
992
1026
|
),
|
|
993
1027
|
|
|
@@ -1109,8 +1143,11 @@ window.__ModuleLoader__.load({
|
|
|
1109
1143
|
'settings.model.loadError': '读取模型列表失败,请重试。',
|
|
1110
1144
|
'settings.model.placeholder': '还没选过模型',
|
|
1111
1145
|
'settings.context.title': '参考之前的对话',
|
|
1112
|
-
'settings.context.on': '
|
|
1113
|
-
'settings.context.off': '
|
|
1146
|
+
'settings.context.on': '开启:参考前文的目标与已排除方案,更耗 token。',
|
|
1147
|
+
'settings.context.off': '关闭:只看当前输入。',
|
|
1148
|
+
// One short line, merged into the hint above rather than added as its
|
|
1149
|
+
// own row: the dot's meaning is a detail of this switch.
|
|
1150
|
+
'settings.context.mark': '蓝点=本次会参考上下文。',
|
|
1114
1151
|
'settings.images.title': '参考输入框里的图片',
|
|
1115
1152
|
'settings.images.on': '开启:输入框里的图片一并参考(历史图片始终不读)。会多耗 token。',
|
|
1116
1153
|
'settings.images.off': '关闭:只处理文字。',
|
|
@@ -1140,8 +1177,9 @@ window.__ModuleLoader__.load({
|
|
|
1140
1177
|
'settings.model.loadError': 'Could not load the model list. Please retry.',
|
|
1141
1178
|
'settings.model.placeholder': 'No model chosen yet',
|
|
1142
1179
|
'settings.context.title': 'Use earlier messages',
|
|
1143
|
-
'settings.context.on': 'On:
|
|
1144
|
-
'settings.context.off': 'Off:
|
|
1180
|
+
'settings.context.on': 'On: uses earlier goals and ruled-out options; costs more tokens.',
|
|
1181
|
+
'settings.context.off': 'Off: uses only what you typed.',
|
|
1182
|
+
'settings.context.mark': 'Blue dot = this run uses context.',
|
|
1145
1183
|
'settings.images.title': 'Use images in the composer',
|
|
1146
1184
|
'settings.images.on': 'On: images already attached to your draft are included. Earlier images never are. Costs more tokens.',
|
|
1147
1185
|
'settings.images.off': 'Off: text only.',
|
package/index.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import fs from 'node:fs';
|
|
19
19
|
import os from 'node:os';
|
|
20
20
|
import path from 'node:path';
|
|
21
|
+
import { fileURLToPath } from 'node:url';
|
|
21
22
|
import { zstdDecompressSync } from 'node:zlib';
|
|
22
23
|
import z from '@deepseek-ai/schemastery';
|
|
23
24
|
|
|
@@ -1102,6 +1103,58 @@ function settingsNamespace(ctx) {
|
|
|
1102
1103
|
return undefined;
|
|
1103
1104
|
}
|
|
1104
1105
|
|
|
1106
|
+
/**
|
|
1107
|
+
* Package facts the settings page shows: version and project URL.
|
|
1108
|
+
*
|
|
1109
|
+
* Read from this package's own `package.json` at runtime rather than hard-coded,
|
|
1110
|
+
* so bumping the manifest is the only step a release needs. Cached after the first
|
|
1111
|
+
* read: the file cannot change while the plugin is loaded.
|
|
1112
|
+
*
|
|
1113
|
+
* @returns `{ version, url }`; fields are undefined when the manifest is absent.
|
|
1114
|
+
*/
|
|
1115
|
+
function readAbout() {
|
|
1116
|
+
if (aboutCache !== undefined) return aboutCache;
|
|
1117
|
+
let version;
|
|
1118
|
+
let url;
|
|
1119
|
+
try {
|
|
1120
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(packageRoot(), 'package.json'), 'utf8'));
|
|
1121
|
+
version = typeof manifest.version === 'string' ? manifest.version : undefined;
|
|
1122
|
+
// `repository` may be a string or `{ url }`; strip the git+ prefix and .git
|
|
1123
|
+
// suffix so it is directly openable in a browser.
|
|
1124
|
+
const raw = typeof manifest.repository === 'string' ? manifest.repository : manifest.repository?.url;
|
|
1125
|
+
if (typeof raw === 'string') {
|
|
1126
|
+
url = raw
|
|
1127
|
+
.replace(/^git\+/u, '')
|
|
1128
|
+
.replace(/\.git$/u, '')
|
|
1129
|
+
.replace(/^git:\/\//u, 'https://');
|
|
1130
|
+
}
|
|
1131
|
+
} catch {
|
|
1132
|
+
// A missing manifest simply hides the version line; it must not break the page.
|
|
1133
|
+
}
|
|
1134
|
+
aboutCache = { version, url };
|
|
1135
|
+
return aboutCache;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
/**
|
|
1139
|
+
* Directory holding this package's manifest.
|
|
1140
|
+
*
|
|
1141
|
+
* `fileURLToPath` is required rather than reading `url.pathname`: a pathname keeps
|
|
1142
|
+
* percent-encoding, so an install directory containing a space ("DSH project")
|
|
1143
|
+
* decoded to a literal `%20` and the manifest read failed silently.
|
|
1144
|
+
*
|
|
1145
|
+
* @returns the package root path.
|
|
1146
|
+
*/
|
|
1147
|
+
function packageRoot() {
|
|
1148
|
+
try {
|
|
1149
|
+
return path.dirname(fileURLToPath(import.meta.url));
|
|
1150
|
+
} catch {
|
|
1151
|
+
return process.cwd();
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
/** Memoized result of {@link readAbout}. */
|
|
1156
|
+
let aboutCache;
|
|
1157
|
+
|
|
1105
1158
|
/**
|
|
1106
1159
|
* Read the live preference values.
|
|
1107
1160
|
*
|
|
@@ -1147,7 +1200,7 @@ async function handleSettings(ctx, config, request) {
|
|
|
1147
1200
|
if (ns === undefined) return fail('SETTINGS_UNAVAILABLE', '无法定位插件配置项,无法保存选项。');
|
|
1148
1201
|
|
|
1149
1202
|
if (request.method === 'GET') {
|
|
1150
|
-
return Response.json({ ok: true, values: readPreferences(ctx, config) });
|
|
1203
|
+
return Response.json({ ok: true, values: readPreferences(ctx, config), about: readAbout() });
|
|
1151
1204
|
}
|
|
1152
1205
|
|
|
1153
1206
|
let payload;
|
package/package.json
CHANGED