dsh-rss 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/LICENSE +21 -21
- package/README.en.md +7 -4
- package/README.md +3 -3
- package/cordis.patch.yml +20 -20
- package/lib/config.d.ts +1 -0
- package/lib/index.d.ts +9 -1
- package/lib/index.js +13 -3
- package/lib/legacy-settings.d.ts +4 -0
- package/lib/legacy-settings.js +64 -0
- package/lib/settings.d.ts +30 -13
- package/lib/settings.js +13 -0
- package/package.json +4 -3
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 stardustlc
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 stardustlc
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en.md
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://awesome-dsh-plugin.com)
|
|
6
6
|
|
|
7
|
-
DSH (DeepSeek Harness) plugin for RSS/Atom subscriptions: manage feeds, fetch and parse RSS 0.9x / 1.0 / 2.0 and Atom, with OPML bulk import/export, exposing
|
|
7
|
+
DSH (DeepSeek Harness) plugin for RSS/Atom subscriptions: manage feeds, fetch and parse RSS 0.9x / 1.0 / 2.0 and Atom, with OPML bulk import/export, exposing nine model-facing tools.
|
|
8
8
|
|
|
9
9
|
## Compatibility
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Version 0.4.0 supports official-source Harness **0.1.7-alpha.2** (2026-09-23, with a local `Symbol.for` tool-scheduler fix). All 18 plugins load together; tool contracts, subscription updates and restart persistence pass in isolation. Live feeds require working network access. Requires Node 22.19 or later within 22.x, or 24 or later.
|
|
12
12
|
|
|
13
13
|
Fetches honor the Harness cancellation signal through DNS, response streaming, and cross-feed searches. Hostname preflight checks reject loopback, private, and link-local addresses by default, including redirect destinations. Set `allowPrivateNetwork: true` for trusted internal feeds.
|
|
14
14
|
|
|
@@ -20,7 +20,7 @@ Fetches honor the Harness cancellation signal through DNS, response streaming, a
|
|
|
20
20
|
dsh plugin --profile web add dsh-rss
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
Restart the web service after installing.
|
|
23
|
+
Restart the web service after installing. Ask your assistant to subscribe to an RSS URL or list your subscriptions; ordinary subscription management needs no configuration-file editing.
|
|
24
24
|
|
|
25
25
|
## Uninstall
|
|
26
26
|
|
|
@@ -61,6 +61,9 @@ Override the plugin row in your profile's `cordis.patch.yml` (the plugin also lo
|
|
|
61
61
|
| `rss_opml_export` | Export subscriptions as OPML 2.0 text (optionally write a file) | `path` optional |
|
|
62
62
|
| `rss_opml_import` | Bulk-import subscriptions from OPML 2.0 text | `opml` required |
|
|
63
63
|
|
|
64
|
+
| `rss_search` | Search across feeds | `query` required; optional feed, date and limit filters |
|
|
65
|
+
| `rss_health` | Check configuration, feeds and cursors offline | none |
|
|
66
|
+
|
|
64
67
|
### Examples
|
|
65
68
|
|
|
66
69
|
```text
|
|
@@ -73,7 +76,7 @@ rss_opml_import { opml: "<?xml version=\"1.0\"?>..." }
|
|
|
73
76
|
|
|
74
77
|
## Subscriptions
|
|
75
78
|
|
|
76
|
-
|
|
79
|
+
On Harness 0.1.7, subscriptions and read cursors are stored in the current profile’s `rss` entry. Changes apply immediately and survive restart. Default installations automatically import the retired `dsh-rss` section from `settings.yaml` or `settings.yaml.imported` once, preserving the original file and existing profile values. Older hosts retain their original settings storage. Use a URL to distinguish feeds with identical names.
|
|
77
80
|
|
|
78
81
|
## Proxy
|
|
79
82
|
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ DSH(DeepSeek Harness)的 RSS/Atom 订阅工具插件:管理订阅源,抓
|
|
|
13
13
|
|
|
14
14
|
## 兼容性
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
0.4.0 适配官方源码构建的 Harness **0.1.7-alpha.2**(2026-09-23,含本地工具调度器 `Symbol.for` 修复)。18 个插件同载、工具契约、订阅读写与重启持久化通过隔离验证;真实外部订阅源需要正常网络连接。Node 要求为 22.19 及以上的 22.x,或 24 及以上。
|
|
17
17
|
|
|
18
18
|
抓取接收 Harness 的取消信号,取消 DNS、网络读取或跨源搜索时保留原始取消原因。默认预检域名解析结果并拒绝回环、私网和链路本地地址;每次重定向都重新校验。可信内网源可显式配置 `allowPrivateNetwork: true`。
|
|
19
19
|
|
|
@@ -25,7 +25,7 @@ DSH(DeepSeek Harness)的 RSS/Atom 订阅工具插件:管理订阅源,抓
|
|
|
25
25
|
dsh plugin --profile web add dsh-rss
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
安装后重启 Web
|
|
28
|
+
安装后重启 Web 服务即可。直接对助手说「订阅这个 RSS 地址,命名为技术资讯」或「列出我的订阅」即可使用,日常增删订阅不需要编辑配置文件。
|
|
29
29
|
|
|
30
30
|
## 卸载
|
|
31
31
|
|
|
@@ -80,7 +80,7 @@ rss_opml_import { opml: "<?xml version=\"1.0\"?>..." }
|
|
|
80
80
|
|
|
81
81
|
## 订阅存储
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
Harness 0.1.7 把订阅列表和读取游标保存在当前 profile 的 `rss` 配置行;增删后立即生效,重启仍保留。默认安装会自动导入旧 `settings.yaml` 或 `settings.yaml.imported` 的 `dsh-rss` 数据一次,保留原文件,且不覆盖已有 profile 值。旧版宿主继续使用原 settings 存储。同名订阅请用 URL 区分。
|
|
84
84
|
|
|
85
85
|
## 特殊代理(梯子)
|
|
86
86
|
|
package/cordis.patch.yml
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
# dsh-rss 组合包补丁:把 RSS 订阅工具插件行插入 profile。
|
|
2
|
-
# 本补丁按 id 覆盖;用户应在自己 profile 的 cordis.patch.yml 里覆盖本行的整个
|
|
3
|
-
# config(见 README 的配置示例)。配置缺失时插件仍会加载,但每个工具在调用时
|
|
4
|
-
# 会抛出带中文指引的错误,提示补全配置后重启。
|
|
5
|
-
#
|
|
6
|
-
# 示例(用户 profile 的 cordis.patch.yml):
|
|
7
|
-
# - id: rss
|
|
8
|
-
# name: 'dsh-rss'
|
|
9
|
-
# config:
|
|
10
|
-
# # proxyUrl: http://127.0.0.1:7890 # 部分订阅源需要特殊代理(梯子)时启用
|
|
11
|
-
# timeoutMs: 15000 # 抓取超时(毫秒)
|
|
12
|
-
# # feedsYaml: | # 可选:预置订阅列表(也可用 rss_add 工具添加)
|
|
13
|
-
# # - url: https://example.com/feed.xml
|
|
14
|
-
# # name: 示例订阅
|
|
15
|
-
#
|
|
16
|
-
- insert:
|
|
17
|
-
- id: rss
|
|
18
|
-
name: 'dsh-rss'
|
|
19
|
-
config:
|
|
20
|
-
timeoutMs: 15000
|
|
1
|
+
# dsh-rss 组合包补丁:把 RSS 订阅工具插件行插入 profile。
|
|
2
|
+
# 本补丁按 id 覆盖;用户应在自己 profile 的 cordis.patch.yml 里覆盖本行的整个
|
|
3
|
+
# config(见 README 的配置示例)。配置缺失时插件仍会加载,但每个工具在调用时
|
|
4
|
+
# 会抛出带中文指引的错误,提示补全配置后重启。
|
|
5
|
+
#
|
|
6
|
+
# 示例(用户 profile 的 cordis.patch.yml):
|
|
7
|
+
# - id: rss
|
|
8
|
+
# name: 'dsh-rss'
|
|
9
|
+
# config:
|
|
10
|
+
# # proxyUrl: http://127.0.0.1:7890 # 部分订阅源需要特殊代理(梯子)时启用
|
|
11
|
+
# timeoutMs: 15000 # 抓取超时(毫秒)
|
|
12
|
+
# # feedsYaml: | # 可选:预置订阅列表(也可用 rss_add 工具添加)
|
|
13
|
+
# # - url: https://example.com/feed.xml
|
|
14
|
+
# # name: 示例订阅
|
|
15
|
+
#
|
|
16
|
+
- insert:
|
|
17
|
+
- id: rss
|
|
18
|
+
name: 'dsh-rss'
|
|
19
|
+
config:
|
|
20
|
+
timeoutMs: 15000
|
package/lib/config.d.ts
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -28,10 +28,18 @@ type RssPreExecuteListener = (exec: RssPendingToolExecution, next: () => Promise
|
|
|
28
28
|
/** 插件所需的最小 ctx 面(社区插件不依赖宿主内部类型)。 */
|
|
29
29
|
export interface RssPluginContext {
|
|
30
30
|
settings: {
|
|
31
|
-
register(ns: string, schema: unknown, options?: {
|
|
31
|
+
register?(ns: string, schema: unknown, options?: {
|
|
32
32
|
base?: Record<string, unknown>;
|
|
33
33
|
applies?: string;
|
|
34
34
|
}): RssSettingsScope;
|
|
35
|
+
update?(ns: string, patch: Record<string, unknown>): Promise<void>;
|
|
36
|
+
};
|
|
37
|
+
fiber?: {
|
|
38
|
+
entry?: {
|
|
39
|
+
options: {
|
|
40
|
+
id: string;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
35
43
|
};
|
|
36
44
|
tools: {
|
|
37
45
|
register(definition: RssToolDefinition): () => void;
|
package/lib/index.js
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
* @module dsh-rss
|
|
8
8
|
*/
|
|
9
9
|
import { resolveConfig } from './config.js';
|
|
10
|
-
import { RSS_SETTINGS_NAMESPACE, RssSettingsSchema } from './settings.js';
|
|
10
|
+
import { RSS_SETTINGS_NAMESPACE, RssSettingsSchema, liveConfig } from './settings.js';
|
|
11
11
|
import { buildRssTools } from './tools.js';
|
|
12
|
+
import { installLegacySettingsImport } from './legacy-settings.js';
|
|
12
13
|
/** cordis 服务注入:apply 里要用 ctx.settings 与 ctx.tools,必须显式声明,否则宿主会抛 cannot get property without inject。 */
|
|
13
14
|
export const name = 'rss';
|
|
14
15
|
export const inject = ['settings', 'tools'];
|
|
@@ -18,11 +19,20 @@ export const inject = ['settings', 'tools'];
|
|
|
18
19
|
* @param config - 插件配置(可缺省)。
|
|
19
20
|
*/
|
|
20
21
|
export function apply(ctx, config) {
|
|
22
|
+
config = liveConfig(config ?? {});
|
|
21
23
|
const cfg = resolveConfig(config);
|
|
22
|
-
|
|
24
|
+
installLegacySettingsImport(ctx, config, RSS_SETTINGS_NAMESPACE, 'rss', ['feedsYaml', 'cursorsJson']);
|
|
25
|
+
const settingsScope = typeof ctx.settings.register === 'function' ? ctx.settings.register(RSS_SETTINGS_NAMESPACE, RssSettingsSchema, {
|
|
23
26
|
base: { feedsYaml: cfg.feedsYaml },
|
|
24
27
|
applies: 'live',
|
|
25
|
-
})
|
|
28
|
+
}) : {
|
|
29
|
+
get: () => ({ feedsYaml: config?.feedsYaml ?? '', cursorsJson: config?.cursorsJson ?? '' }),
|
|
30
|
+
update: async (patch) => {
|
|
31
|
+
if (!ctx.settings.update)
|
|
32
|
+
throw new Error('当前宿主不支持保存 RSS 配置');
|
|
33
|
+
await ctx.settings.update(ctx.fiber?.entry?.options.id ?? 'rss', patch);
|
|
34
|
+
},
|
|
35
|
+
};
|
|
26
36
|
const disposers = [];
|
|
27
37
|
for (const definition of buildRssTools(cfg, settingsScope)) {
|
|
28
38
|
disposers.push(ctx.tools.register(definition));
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** No backup is edited or deleted; the completion marker lives beside imported values. */
|
|
2
|
+
export declare function importLegacySettings(ctx: any, config: Record<string, any>, namespace: string, entryId: string, fields: readonly string[], home?: string): Promise<boolean>;
|
|
3
|
+
/** Defer persistence until the entry and settings provider are active. */
|
|
4
|
+
export declare function installLegacySettingsImport(ctx: any, config: Record<string, any>, namespace: string, entryId: string, fields: readonly string[]): void;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** Import only this plugin's retired settings section, preserving profile overrides. */
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join, resolve } from 'node:path';
|
|
5
|
+
import { parse } from 'yaml';
|
|
6
|
+
function plain(value) {
|
|
7
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
function missing(legacy, current) {
|
|
10
|
+
const patch = {};
|
|
11
|
+
for (const [key, value] of Object.entries(legacy)) {
|
|
12
|
+
if (current[key] === undefined)
|
|
13
|
+
patch[key] = value;
|
|
14
|
+
else if (plain(value) && plain(current[key])) {
|
|
15
|
+
const nested = missing(value, current[key]);
|
|
16
|
+
if (Object.keys(nested).length)
|
|
17
|
+
patch[key] = nested;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return patch;
|
|
21
|
+
}
|
|
22
|
+
/** No backup is edited or deleted; the completion marker lives beside imported values. */
|
|
23
|
+
export async function importLegacySettings(ctx, config, namespace, entryId, fields, home) {
|
|
24
|
+
if (typeof ctx.settings.register === 'function' || config.legacySettingsImported === true)
|
|
25
|
+
return false;
|
|
26
|
+
// Old namespaces were global. Do not copy credentials into unrelated custom instances.
|
|
27
|
+
if (ctx.fiber?.entry?.options.id !== entryId)
|
|
28
|
+
return false;
|
|
29
|
+
let base = home ?? (process.env.DSH_HOME?.trim() || join(homedir(), '.dsh'));
|
|
30
|
+
if (base === '~')
|
|
31
|
+
base = homedir();
|
|
32
|
+
else if (base.startsWith('~/') || base.startsWith('~\\'))
|
|
33
|
+
base = join(homedir(), base.slice(2));
|
|
34
|
+
let document;
|
|
35
|
+
for (const file of ['settings.yaml.imported', 'settings.yaml']) {
|
|
36
|
+
try {
|
|
37
|
+
document = parse(readFileSync(resolve(base, file), 'utf8'));
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (error.code !== 'ENOENT')
|
|
42
|
+
throw new Error('Cannot read legacy settings; original file preserved');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (!plain(document) || !plain(document[namespace]))
|
|
46
|
+
return false;
|
|
47
|
+
const section = Object.fromEntries(fields.filter(key => Object.hasOwn(document[namespace], key)).map(key => [key, document[namespace][key]]));
|
|
48
|
+
if (Object.keys(section).length === 0)
|
|
49
|
+
return false;
|
|
50
|
+
await ctx.settings.update(entryId, { ...missing(section, { ...config }), legacySettingsImported: true });
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
/** Defer persistence until the entry and settings provider are active. */
|
|
54
|
+
export function installLegacySettingsImport(ctx, config, namespace, entryId, fields) {
|
|
55
|
+
if (typeof ctx.settings.register === 'function' || typeof ctx.inject !== 'function')
|
|
56
|
+
return;
|
|
57
|
+
ctx.inject(['appReady'], (readyCtx) => {
|
|
58
|
+
readyCtx.effect(() => readyCtx.appReady.onReady(() => {
|
|
59
|
+
void importLegacySettings(ctx, config, namespace, entryId, fields).catch(() => {
|
|
60
|
+
ctx.logger?.warn?.(namespace + ': legacy settings could not be imported; the original settings file is preserved.');
|
|
61
|
+
});
|
|
62
|
+
}));
|
|
63
|
+
});
|
|
64
|
+
}
|
package/lib/settings.d.ts
CHANGED
|
@@ -1,19 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import modern from '@deepseek-ai/schemastery';
|
|
2
|
+
export declare const Config: modern<Schemastery.ObjectS<NoInfer<{
|
|
3
|
+
feedsYaml: modern<string, string, "volatile">;
|
|
4
|
+
cursorsJson: modern<string, string, "volatile">;
|
|
5
|
+
proxyUrl: modern<string, string, "plain">;
|
|
6
|
+
timeoutMs: modern<number, number, "plain">;
|
|
7
|
+
maxBodyBytes: modern<number, number, "plain">;
|
|
8
|
+
userAgent: modern<string, string, "plain">;
|
|
9
|
+
allowPrivateNetwork: modern<boolean, boolean, "plain">;
|
|
10
|
+
opmlWriteApproval: modern<boolean, boolean, "plain">;
|
|
11
|
+
legacySettingsImported: modern<boolean, boolean, "volatile">;
|
|
12
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
13
|
+
feedsYaml: modern<string, string, "volatile">;
|
|
14
|
+
cursorsJson: modern<string, string, "volatile">;
|
|
15
|
+
proxyUrl: modern<string, string, "plain">;
|
|
16
|
+
timeoutMs: modern<number, number, "plain">;
|
|
17
|
+
maxBodyBytes: modern<number, number, "plain">;
|
|
18
|
+
userAgent: modern<string, string, "plain">;
|
|
19
|
+
allowPrivateNetwork: modern<boolean, boolean, "plain">;
|
|
20
|
+
opmlWriteApproval: modern<boolean, boolean, "plain">;
|
|
21
|
+
legacySettingsImported: modern<boolean, boolean, "volatile">;
|
|
22
|
+
}>>, "plain">;
|
|
23
|
+
export declare function liveConfig<T extends object>(config: T): T;
|
|
7
24
|
/** 本插件拥有的 settings 文档命名空间。 */
|
|
8
25
|
export declare const RSS_SETTINGS_NAMESPACE = "dsh-rss";
|
|
9
26
|
/** settings 页形状:目前只有订阅列表(YAML 文本)。 */
|
|
10
|
-
export declare const RssSettingsSchema:
|
|
11
|
-
feedsYaml:
|
|
12
|
-
cursorsJson:
|
|
13
|
-
}
|
|
14
|
-
feedsYaml:
|
|
15
|
-
cursorsJson:
|
|
16
|
-
}
|
|
27
|
+
export declare const RssSettingsSchema: modern<Schemastery.ObjectS<NoInfer<{
|
|
28
|
+
feedsYaml: modern<string, string, Mode extends "volatile-defined" | "volatile" ? "volatile-defined" : "defined">;
|
|
29
|
+
cursorsJson: modern<string, string, Mode extends "volatile-defined" | "volatile" ? "volatile-defined" : "defined">;
|
|
30
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
31
|
+
feedsYaml: modern<string, string, Mode extends "volatile-defined" | "volatile" ? "volatile-defined" : "defined">;
|
|
32
|
+
cursorsJson: modern<string, string, Mode extends "volatile-defined" | "volatile" ? "volatile-defined" : "defined">;
|
|
33
|
+
}>>, "plain">;
|
|
17
34
|
/** settings 解析后的值。 */
|
|
18
35
|
export interface RssSettingsValue {
|
|
19
36
|
feedsYaml: string;
|
package/lib/settings.js
CHANGED
|
@@ -4,6 +4,19 @@
|
|
|
4
4
|
* @module dsh-rss/settings
|
|
5
5
|
*/
|
|
6
6
|
import z from 'schemastery';
|
|
7
|
+
import modern from '@deepseek-ai/schemastery';
|
|
8
|
+
export const Config = modern.object({
|
|
9
|
+
feedsYaml: modern.string().volatile(), cursorsJson: modern.string().volatile(),
|
|
10
|
+
proxyUrl: modern.string(), timeoutMs: modern.number(), maxBodyBytes: modern.number(),
|
|
11
|
+
userAgent: modern.string(), allowPrivateNetwork: modern.boolean(), opmlWriteApproval: modern.boolean(),
|
|
12
|
+
legacySettingsImported: modern.boolean().volatile(),
|
|
13
|
+
});
|
|
14
|
+
export function liveConfig(config) {
|
|
15
|
+
return new Proxy(config, { get(target, key, receiver) {
|
|
16
|
+
const value = Reflect.get(target, key, receiver);
|
|
17
|
+
return value !== null && typeof value === 'object' && typeof value.get === 'function' ? value.get() : value;
|
|
18
|
+
} });
|
|
19
|
+
}
|
|
7
20
|
/** 本插件拥有的 settings 文档命名空间。 */
|
|
8
21
|
export const RSS_SETTINGS_NAMESPACE = 'dsh-rss';
|
|
9
22
|
/** settings 页形状:目前只有订阅列表(YAML 文本)。 */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-rss",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "DSH RSS
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "DSH RSS 插件:订阅源管理、OPML 导入导出、抓取解析 RSS/Atom 并保留正文。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/index.d.ts",
|
|
@@ -46,7 +46,8 @@
|
|
|
46
46
|
"fast-xml-parser": "^5.0.0",
|
|
47
47
|
"schemastery": "^3.18.0",
|
|
48
48
|
"undici": "^8.10.0",
|
|
49
|
-
"yaml": "^2.9.0"
|
|
49
|
+
"yaml": "^2.9.0",
|
|
50
|
+
"@deepseek-ai/schemastery": "^3.18.3"
|
|
50
51
|
},
|
|
51
52
|
"devDependencies": {
|
|
52
53
|
"@types/node": "^24.0.0",
|