dsh-claude-style 0.3.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.en.md +2 -9
- package/README.md +2 -15
- package/docs/STYLE.md +81 -32
- package/docs/architecture.md +6 -7
- package/lib/client.js +881 -106
- package/lib/index.js +41 -3
- package/lib/model-descriptions.json +46 -2
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -71,6 +71,9 @@ let namespaceState = 'pending'
|
|
|
71
71
|
/** Accepted values, mirrored by src/constants.js. */
|
|
72
72
|
const BRANDS = ['off', 'claude', 'anthropic']
|
|
73
73
|
const COMPOSER_SCOPES = ['off', 'hero', 'conversation', 'all']
|
|
74
|
+
const AUTO_POPOVER_SCOPES = ['off', 'account', 'all']
|
|
75
|
+
/** The official service id, mirrored by src/constants.js. */
|
|
76
|
+
const MODEL_OFFICIAL_GROUP = 'deepseek-official'
|
|
74
77
|
/** Languages the account-hold easter egg's page can be written in. */
|
|
75
78
|
const BAN_LOCALES = ['en', 'zh']
|
|
76
79
|
const USERNAME_MAX = 64
|
|
@@ -79,8 +82,10 @@ const USERNAME_MAX = 64
|
|
|
79
82
|
const PREFS_DEFAULT = Object.freeze({
|
|
80
83
|
brand: 'claude',
|
|
81
84
|
collapseFooter: true,
|
|
82
|
-
autoPopover:
|
|
85
|
+
autoPopover: 'all',
|
|
83
86
|
composerScope: 'all',
|
|
87
|
+
modelPicker: true,
|
|
88
|
+
quickProviders: [],
|
|
84
89
|
username: '',
|
|
85
90
|
banLocale: 'en',
|
|
86
91
|
})
|
|
@@ -126,21 +131,52 @@ function buildPrefsSchema(Schema) {
|
|
|
126
131
|
collapseFooter: Schema.any().default(PREFS_DEFAULT.collapseFooter),
|
|
127
132
|
autoPopover: Schema.any().default(PREFS_DEFAULT.autoPopover),
|
|
128
133
|
composerScope: Schema.any().default(PREFS_DEFAULT.composerScope),
|
|
134
|
+
modelPicker: Schema.any().default(PREFS_DEFAULT.modelPicker),
|
|
135
|
+
quickProviders: Schema.any().default(PREFS_DEFAULT.quickProviders),
|
|
129
136
|
username: Schema.any().default(PREFS_DEFAULT.username),
|
|
130
137
|
banLocale: Schema.any().default(PREFS_DEFAULT.banLocale),
|
|
131
138
|
})
|
|
132
139
|
}
|
|
133
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Clamp the hover-open preference. It used to be a boolean, and a value stored
|
|
143
|
+
* in that shape still has to land on a scope: `true` meant every popover,
|
|
144
|
+
* `false` meant click-only.
|
|
145
|
+
*/
|
|
146
|
+
function normalizeAutoPopover(value) {
|
|
147
|
+
if (value === true) return 'all'
|
|
148
|
+
if (value === false) return 'off'
|
|
149
|
+
return AUTO_POPOVER_SCOPES.includes(value) ? value : PREFS_DEFAULT.autoPopover
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* The provider ids the picker's first level carries: strings, deduped, order
|
|
154
|
+
* kept. Ids rather than names so a catalog rename cannot drop the selection.
|
|
155
|
+
* The official service is the picker's default, not a choice, so a stored id
|
|
156
|
+
* for it is dropped — the first level shows it whenever nothing else is picked.
|
|
157
|
+
*/
|
|
158
|
+
function normalizeQuickProviders(value) {
|
|
159
|
+
if (!Array.isArray(value)) return []
|
|
160
|
+
const out = []
|
|
161
|
+
for (const id of value) {
|
|
162
|
+
if (typeof id !== 'string' || id === '' || id === MODEL_OFFICIAL_GROUP || out.includes(id)) continue
|
|
163
|
+
out.push(id)
|
|
164
|
+
}
|
|
165
|
+
return out
|
|
166
|
+
}
|
|
167
|
+
|
|
134
168
|
/** Clamp one stored section into the preference shape (the schema stores `any`). */
|
|
135
169
|
function normalizePrefs(value) {
|
|
136
170
|
const section = value !== null && typeof value === 'object' ? value : {}
|
|
137
171
|
return {
|
|
138
172
|
brand: BRANDS.includes(section.brand) ? section.brand : PREFS_DEFAULT.brand,
|
|
139
173
|
collapseFooter: section.collapseFooter !== false,
|
|
140
|
-
autoPopover: section.autoPopover
|
|
174
|
+
autoPopover: normalizeAutoPopover(section.autoPopover),
|
|
141
175
|
composerScope: COMPOSER_SCOPES.includes(section.composerScope)
|
|
142
176
|
? section.composerScope
|
|
143
177
|
: PREFS_DEFAULT.composerScope,
|
|
178
|
+
modelPicker: section.modelPicker !== false,
|
|
179
|
+
quickProviders: normalizeQuickProviders(section.quickProviders),
|
|
144
180
|
username: typeof section.username === 'string'
|
|
145
181
|
? section.username.trim().slice(0, USERNAME_MAX)
|
|
146
182
|
: PREFS_DEFAULT.username,
|
|
@@ -350,7 +386,9 @@ export function apply(ctx) {
|
|
|
350
386
|
const patch = {}
|
|
351
387
|
if (BRANDS.includes(body.brand)) patch.brand = body.brand
|
|
352
388
|
if (typeof body.collapseFooter === 'boolean') patch.collapseFooter = body.collapseFooter
|
|
353
|
-
if (typeof body.autoPopover === 'boolean') patch.autoPopover = body.autoPopover
|
|
389
|
+
if (typeof body.autoPopover === 'boolean' || AUTO_POPOVER_SCOPES.includes(body.autoPopover)) patch.autoPopover = body.autoPopover
|
|
390
|
+
if (typeof body.modelPicker === 'boolean') patch.modelPicker = body.modelPicker
|
|
391
|
+
if (Array.isArray(body.quickProviders)) patch.quickProviders = normalizeQuickProviders(body.quickProviders)
|
|
354
392
|
if (COMPOSER_SCOPES.includes(body.composerScope)) patch.composerScope = body.composerScope
|
|
355
393
|
if (typeof body.username === 'string') patch.username = body.username.trim().slice(0, USERNAME_MAX)
|
|
356
394
|
if (BAN_LOCALES.includes(body.banLocale)) patch.banLocale = body.banLocale
|
|
@@ -57,8 +57,20 @@
|
|
|
57
57
|
"en": "Open popovers on hover"
|
|
58
58
|
},
|
|
59
59
|
"autoPopoverDesc": {
|
|
60
|
-
"zh": "
|
|
61
|
-
"en": "
|
|
60
|
+
"zh": "哪些弹层悬停即展开。「仅账号区」只让侧栏账户弹层这样;「全部」再加上权限、模型、会话统计与首页的目录/预设。",
|
|
61
|
+
"en": "Which popovers hover opens. \"Account only\" keeps it to the sidebar account popover; \"All\" adds the permission, model, session-stats and the home page's workspace and preset pickers."
|
|
62
|
+
},
|
|
63
|
+
"autoPopoverOff": {
|
|
64
|
+
"zh": "关闭",
|
|
65
|
+
"en": "Off"
|
|
66
|
+
},
|
|
67
|
+
"autoPopoverAccount": {
|
|
68
|
+
"zh": "仅账号区",
|
|
69
|
+
"en": "Account only"
|
|
70
|
+
},
|
|
71
|
+
"autoPopoverAll": {
|
|
72
|
+
"zh": "全部",
|
|
73
|
+
"en": "All"
|
|
62
74
|
},
|
|
63
75
|
"composerTitle": {
|
|
64
76
|
"zh": "对话框样式改动范围",
|
|
@@ -68,6 +80,38 @@
|
|
|
68
80
|
"zh": "重绘输入区,可选新会话页、对话内或两者。",
|
|
69
81
|
"en": "Which input area the skin restyles: the new-conversation page, the conversation, or both. The hero brand mark and headline are unaffected."
|
|
70
82
|
},
|
|
83
|
+
"pickerTitle": {
|
|
84
|
+
"zh": "重做模型选择器",
|
|
85
|
+
"en": "Redraw the model picker"
|
|
86
|
+
},
|
|
87
|
+
"pickerDesc": {
|
|
88
|
+
"zh": "把输入框的模型席位换成 Claude 风格的两级弹层。关闭后交回系统自己的模型菜单,输入区其余改动不受影响。",
|
|
89
|
+
"en": "Replace the composer's model seat with the two-level Claude-style menu. Off hands the model menu back to the host; the rest of the composer restyle is unaffected."
|
|
90
|
+
},
|
|
91
|
+
"quickTitle": {
|
|
92
|
+
"zh": "快捷供应商",
|
|
93
|
+
"en": "Quick providers"
|
|
94
|
+
},
|
|
95
|
+
"quickDesc": {
|
|
96
|
+
"zh": "官方服务始终列在一级弹层最前面,不在这份清单里;勾选的供应商跟在它后面,各自的模型之间用一条横线分隔。已被移除的供应商会留在清单里,带「已移除」标记,取消勾选即可清除。",
|
|
97
|
+
"en": "The official service always leads the picker's first level and is not listed here; picked providers follow it, one rule between providers. A provider removed from the catalog stays in the list, marked \"Removed\", and can be unchecked to clear it."
|
|
98
|
+
},
|
|
99
|
+
"quickNone": {
|
|
100
|
+
"zh": "未选择",
|
|
101
|
+
"en": "None"
|
|
102
|
+
},
|
|
103
|
+
"quickCount": {
|
|
104
|
+
"zh": "{count} 个供应商",
|
|
105
|
+
"en": "{count} providers"
|
|
106
|
+
},
|
|
107
|
+
"quickLoading": {
|
|
108
|
+
"zh": "正在加载模型目录…",
|
|
109
|
+
"en": "Loading providers…"
|
|
110
|
+
},
|
|
111
|
+
"quickRemoved": {
|
|
112
|
+
"zh": "已移除",
|
|
113
|
+
"en": "Removed"
|
|
114
|
+
},
|
|
71
115
|
"usernameTitle": {
|
|
72
116
|
"zh": "用户名",
|
|
73
117
|
"en": "Username"
|
package/package.json
CHANGED