dsh-any-deepseek 0.0.1 → 0.0.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.
- package/lib/client.js +10 -4
- package/lib/config.d.ts +24 -5
- package/lib/index.js +21 -5
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -199,15 +199,21 @@ window.__ModuleLoader__.load({
|
|
|
199
199
|
* Run one settings write and surface a refusal.
|
|
200
200
|
*
|
|
201
201
|
* A write can be refused for reasons the user can act on (read-only deployment, the settings
|
|
202
|
-
* service not composed, a revision conflict
|
|
203
|
-
*
|
|
204
|
-
*
|
|
202
|
+
* service not composed, a revision conflict, a field the host considers non-volatile) and for
|
|
203
|
+
* reasons they cannot (transport). Both are facts, and silently discarding them is what makes
|
|
204
|
+
* a panel look alive while nothing is saved.
|
|
205
|
+
*
|
|
206
|
+
* 🔴 **The refusal message must NOT name causes we have not checked.** This used to read
|
|
207
|
+
* "只读部署,或设置服务未启用" — and the one time it actually fired, the real cause was
|
|
208
|
+
* neither: `current` was missing `.volatile()` in the schema, three layers away. Naming two
|
|
209
|
+
* unchecked causes sent the investigation in the wrong direction. A refusal is a refusal:
|
|
210
|
+
* say that, and let the host's own error speak for itself.
|
|
205
211
|
* @param run - the write.
|
|
206
212
|
* @param context - what the user was trying to do.
|
|
207
213
|
*/
|
|
208
214
|
const write = (run, context = "保存失败") => {
|
|
209
215
|
run().then((accepted) => {
|
|
210
|
-
if (!accepted) setError(`${context}
|
|
216
|
+
if (!accepted) setError(`${context}:宿主拒绝了这个修改`);
|
|
211
217
|
else setError(null);
|
|
212
218
|
}, (cause) => {
|
|
213
219
|
setError(`${context}:${cause instanceof Error ? cause.message : String(cause)}`);
|
package/lib/config.d.ts
CHANGED
|
@@ -101,20 +101,39 @@ export interface PluginConfigInput {
|
|
|
101
101
|
/**
|
|
102
102
|
* Plugin configuration as the plugin reads it (schema OUTPUT).
|
|
103
103
|
*
|
|
104
|
-
* `channels`
|
|
105
|
-
*
|
|
104
|
+
* `channels` and `current` parse to reference wrappers — created even when the user set
|
|
105
|
+
* nothing, so the fields are always present. Read them through {@link unwrap}.
|
|
106
|
+
*
|
|
107
|
+
* 🔴 **`current` is volatile too, and that is not cosmetic** — see the `.volatile()` note on
|
|
108
|
+
* `PluginConfigSchema`.
|
|
106
109
|
*/
|
|
107
110
|
export interface PluginConfigValue {
|
|
108
111
|
channels: Volatile<Record<string, ChannelConfigValue>>;
|
|
109
|
-
current: string
|
|
112
|
+
current: Volatile<string>;
|
|
110
113
|
usage: UsageConfigValue;
|
|
111
114
|
fallback: string[];
|
|
112
115
|
}
|
|
113
116
|
/**
|
|
114
117
|
* Plugin configuration schema.
|
|
115
118
|
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
119
|
+
* ## Why EVERY panel-writable field must be `.volatile()`
|
|
120
|
+
*
|
|
121
|
+
* The host projects an entry's Config into a settings form only for volatile fields, and its
|
|
122
|
+
* write path **refuses** any path outside one:
|
|
123
|
+
*
|
|
124
|
+
* ```js
|
|
125
|
+
* for (const path of paths) if (path.length && !isVolatilePath(schema, path))
|
|
126
|
+
* throw new Error(`Config field "${path.join('.')}" is not volatile`)
|
|
127
|
+
* ```
|
|
128
|
+
*
|
|
129
|
+
* `channels` was volatile from the start, so channel edits worked. `current` was **not**, so
|
|
130
|
+
* every click on "设为当前" was rejected by the host — and the host's client-side form turns
|
|
131
|
+
* that refusal into a bare `false`, which the panel reported as "read-only deployment or the
|
|
132
|
+
* settings service is not enabled". **That message named two causes it had never checked.**
|
|
133
|
+
* The real cause was a schema annotation three layers away.
|
|
134
|
+
*
|
|
135
|
+
* ⇒ Rule: a field the panel writes must be `.volatile()`, and the runtime side must
|
|
136
|
+
* `unwrap()` it. Adding a writable field without both halves reproduces this bug silently.
|
|
118
137
|
*/
|
|
119
138
|
export declare const PluginConfigSchema: SchemaOf<PluginConfigInput, PluginConfigValue>;
|
|
120
139
|
/**
|
package/lib/index.js
CHANGED
|
@@ -72,12 +72,28 @@ const UsageConfigSchema = z.object({
|
|
|
72
72
|
/**
|
|
73
73
|
* Plugin configuration schema.
|
|
74
74
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
75
|
+
* ## Why EVERY panel-writable field must be `.volatile()`
|
|
76
|
+
*
|
|
77
|
+
* The host projects an entry's Config into a settings form only for volatile fields, and its
|
|
78
|
+
* write path **refuses** any path outside one:
|
|
79
|
+
*
|
|
80
|
+
* ```js
|
|
81
|
+
* for (const path of paths) if (path.length && !isVolatilePath(schema, path))
|
|
82
|
+
* throw new Error(`Config field "${path.join('.')}" is not volatile`)
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* `channels` was volatile from the start, so channel edits worked. `current` was **not**, so
|
|
86
|
+
* every click on "设为当前" was rejected by the host — and the host's client-side form turns
|
|
87
|
+
* that refusal into a bare `false`, which the panel reported as "read-only deployment or the
|
|
88
|
+
* settings service is not enabled". **That message named two causes it had never checked.**
|
|
89
|
+
* The real cause was a schema annotation three layers away.
|
|
90
|
+
*
|
|
91
|
+
* ⇒ Rule: a field the panel writes must be `.volatile()`, and the runtime side must
|
|
92
|
+
* `unwrap()` it. Adding a writable field without both halves reproduces this bug silently.
|
|
77
93
|
*/
|
|
78
94
|
const PluginConfigSchema = z.object({
|
|
79
95
|
channels: z.dict(ChannelConfigSchema).default({}).volatile().description("渠道表:每行一个中转渠道"),
|
|
80
|
-
current: z.string().default("").description("当前使用的渠道 id"),
|
|
96
|
+
current: z.string().default("").volatile().description("当前使用的渠道 id"),
|
|
81
97
|
usage: UsageConfigSchema.default({ enabled: true }),
|
|
82
98
|
fallback: z.array(z.string()).default([]).description("预留:故障转移顺序(v1 未实现)")
|
|
83
99
|
});
|
|
@@ -1592,8 +1608,8 @@ function apply(ctx, config) {
|
|
|
1592
1608
|
return enabledChannels(resolveChannels(map), map);
|
|
1593
1609
|
};
|
|
1594
1610
|
const current = () => {
|
|
1595
|
-
const
|
|
1596
|
-
return typeof
|
|
1611
|
+
const value = unwrap((ctx.fiber?.config ?? config).current);
|
|
1612
|
+
return typeof value === "string" ? value : void 0;
|
|
1597
1613
|
};
|
|
1598
1614
|
const adapter = new AnyDeepSeekAdapter({
|
|
1599
1615
|
channels,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-any-deepseek",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "One DeepSeek V4.1 Flash provider for DeepSeek Harness: paste a key per channel, switch channels manually, token usage booked per real upstream.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|