dsh-rss 0.4.1 → 0.4.3
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.en.md +4 -4
- package/README.md +4 -4
- package/lib/feeds.d.ts +4 -2
- package/lib/feeds.js +12 -6
- package/lib/tools.js +3 -3
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# dsh-rss
|
|
2
2
|
|
|
3
|
-
## 0.4.
|
|
3
|
+
## 0.4.3 update (2026-10-01)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Fixes URL comparison for add, remove, OPML import and search. Schemes, hosts and default ports are normalized while case-sensitive paths and query parameters remain distinct, preventing unrelated subscriptions from being merged or removed. Existing Fake-IP DNS guidance and reserved-address checks remain available.
|
|
6
6
|
|
|
7
|
-
Validation host: Harness 0.
|
|
7
|
+
Validation host: Harness `0.2.0-rc.2` built from official sources (commit `639ed01539`) on 2026-10-01. All 81 Windows tests, the 18-plugin co-load and nine RSS tool contracts pass. Production external feeds still require separate network validation.
|
|
8
8
|
|
|
9
9
|
   
|
|
10
10
|
|
|
@@ -14,7 +14,7 @@ DSH (DeepSeek Harness) plugin for RSS/Atom subscriptions: manage feeds, fetch an
|
|
|
14
14
|
|
|
15
15
|
## Compatibility
|
|
16
16
|
|
|
17
|
-
Version 0.4.0 supports
|
|
17
|
+
Version 0.4.0 supports the declarative settings interface introduced in Harness **0.1.7**. The current baseline is official-source **0.2.0-rc.2**. 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.
|
|
18
18
|
|
|
19
19
|
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.
|
|
20
20
|
|
package/README.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
# dsh-rss
|
|
4
4
|
|
|
5
|
-
## 0.4.
|
|
5
|
+
## 0.4.3 更新(2026-10-01)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
修复订阅 URL 的大小写比较:添加、删除、OPML 导入与搜索统一归一化协议、域名和默认端口,保留路径和查询参数的大小写,避免合并或删除不同订阅源。保留此前的代理 Fake-IP DNS 提示和保留地址检查。
|
|
8
8
|
|
|
9
|
-
验证宿主:官方源码构建的 Harness 0.
|
|
9
|
+
验证宿主:官方源码构建的 Harness `0.2.0-rc.2`(commit `639ed01539`,2026-10-01)。81 项 Windows 插件测试、18 个插件共同加载与 9 个 RSS 工具的契约检查通过。真实外部订阅源仍需正常网络连接。
|
|
10
10
|
|
|
11
11
|
> **agent 的资讯雷达**:订阅管理 + RSS/Atom 抓取解析。
|
|
12
12
|
|
|
@@ -19,7 +19,7 @@ DSH(DeepSeek Harness)的 RSS/Atom 订阅工具插件:管理订阅源,抓
|
|
|
19
19
|
|
|
20
20
|
## 兼容性
|
|
21
21
|
|
|
22
|
-
0.4.0
|
|
22
|
+
0.4.0 起适配官方源码构建的 Harness **0.1.7 及以上的声明式设置接口**;当前基线为 **0.2.0-rc.2**,18 个插件同载、工具契约、订阅读写与重启持久化在隔离环境通过验证;真实外部订阅源需要正常网络连接。Node 要求为 22.19 及以上的 22.x,或 24 及以上。
|
|
23
23
|
|
|
24
24
|
抓取接收 Harness 的取消信号,取消 DNS、网络读取或跨源搜索时保留原始取消原因。默认预检域名解析结果并拒绝回环、私网和链路本地地址;每次重定向都重新校验。可信内网源可显式配置 `allowPrivateNetwork: true`。
|
|
25
25
|
|
package/lib/feeds.d.ts
CHANGED
|
@@ -10,8 +10,10 @@ export interface Feed {
|
|
|
10
10
|
export declare function parseFeedsYaml(text: string): Feed[];
|
|
11
11
|
/** 订阅数组序列化回 YAML 文本(带使用说明头)。 */
|
|
12
12
|
export declare function serializeFeeds(feeds: Feed[]): string;
|
|
13
|
+
/** Normalize URL scheme, host and default port while preserving path/query case. */
|
|
14
|
+
export declare function sameFeedUrl(a: string, b: string): boolean;
|
|
13
15
|
/**
|
|
14
|
-
* 添加订阅:按
|
|
16
|
+
* 添加订阅:按 URL 去重,保留路径与查询值的大小写;已存在时合并更新 name/category。
|
|
15
17
|
*/
|
|
16
18
|
export declare function addFeed(feeds: Feed[], url: string, name: string, category: string): {
|
|
17
19
|
feeds: Feed[];
|
|
@@ -19,7 +21,7 @@ export declare function addFeed(feeds: Feed[], url: string, name: string, catego
|
|
|
19
21
|
existed: boolean;
|
|
20
22
|
};
|
|
21
23
|
/**
|
|
22
|
-
* 删除订阅:
|
|
24
|
+
* 删除订阅:URL 路径与查询值精确匹配,或 name 匹配所有同名项(不区分大小写)。
|
|
23
25
|
* 两者都缺或没有匹配项时抛中文错误。
|
|
24
26
|
*/
|
|
25
27
|
export declare function removeFeed(feeds: Feed[], url?: string, name?: string): {
|
package/lib/feeds.js
CHANGED
|
@@ -65,17 +65,23 @@ export function serializeFeeds(feeds) {
|
|
|
65
65
|
const body = YAML.stringify(rows).trimEnd();
|
|
66
66
|
return FEEDS_HEADER.join('\n') + body + '\n';
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
/** Normalize URL scheme, host and default port while preserving path/query case. */
|
|
69
|
+
export function sameFeedUrl(a, b) {
|
|
70
|
+
try {
|
|
71
|
+
return new URL(a.trim()).href === new URL(b.trim()).href;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return a.trim() === b.trim();
|
|
75
|
+
}
|
|
70
76
|
}
|
|
71
77
|
/**
|
|
72
|
-
* 添加订阅:按
|
|
78
|
+
* 添加订阅:按 URL 去重,保留路径与查询值的大小写;已存在时合并更新 name/category。
|
|
73
79
|
*/
|
|
74
80
|
export function addFeed(feeds, url, name, category) {
|
|
75
81
|
const cleanUrl = url.trim();
|
|
76
82
|
const cleanName = name.trim();
|
|
77
83
|
const cleanCategory = category.trim();
|
|
78
|
-
const existing = feeds.find((feed) =>
|
|
84
|
+
const existing = feeds.find((feed) => sameFeedUrl(feed.url, cleanUrl));
|
|
79
85
|
if (existing) {
|
|
80
86
|
const merged = {
|
|
81
87
|
url: existing.url,
|
|
@@ -89,7 +95,7 @@ export function addFeed(feeds, url, name, category) {
|
|
|
89
95
|
return { feeds: [...feeds, added], added, existed: false };
|
|
90
96
|
}
|
|
91
97
|
/**
|
|
92
|
-
* 删除订阅:
|
|
98
|
+
* 删除订阅:URL 路径与查询值精确匹配,或 name 匹配所有同名项(不区分大小写)。
|
|
93
99
|
* 两者都缺或没有匹配项时抛中文错误。
|
|
94
100
|
*/
|
|
95
101
|
export function removeFeed(feeds, url, name) {
|
|
@@ -100,7 +106,7 @@ export function removeFeed(feeds, url, name) {
|
|
|
100
106
|
}
|
|
101
107
|
const removed = [];
|
|
102
108
|
const next = feeds.filter((feed) => {
|
|
103
|
-
const match = (cleanUrl !== '' &&
|
|
109
|
+
const match = (cleanUrl !== '' && sameFeedUrl(feed.url, cleanUrl)) || (cleanName !== '' && feed.name.toLowerCase() === cleanName.toLowerCase());
|
|
104
110
|
if (match)
|
|
105
111
|
removed.push(feed);
|
|
106
112
|
return !match;
|
package/lib/tools.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @module dsh-rss/tools
|
|
6
6
|
*/
|
|
7
7
|
import { writeFile } from 'node:fs/promises';
|
|
8
|
-
import { addFeed, findFeedsByName, parseFeedsYaml, removeFeed, serializeFeeds } from './feeds.js';
|
|
8
|
+
import { addFeed, findFeedsByName, parseFeedsYaml, removeFeed, sameFeedUrl, serializeFeeds } from './feeds.js';
|
|
9
9
|
import { buildOpml, importOpmlFeeds, parseOpml } from './opml.js';
|
|
10
10
|
import { parseFeed } from './parser.js';
|
|
11
11
|
import { assertHttpUrl, fetchFeedXml } from './network.js';
|
|
@@ -461,7 +461,7 @@ export function buildRssTools(config, settingsScope, fetchImpl, lookupImpl) {
|
|
|
461
461
|
};
|
|
462
462
|
const rssRemove = {
|
|
463
463
|
name: 'rss_remove',
|
|
464
|
-
description: '删除已订阅的 RSS/Atom 源。url 与 name 至少给一个:url
|
|
464
|
+
description: '删除已订阅的 RSS/Atom 源。url 与 name 至少给一个:url 的协议、主机大小写与默认端口可归一化,路径和查询值精确匹配;name 匹配所有同名订阅。删除结果持久化到 settings。',
|
|
465
465
|
parameters: compileParameters({
|
|
466
466
|
url: { type: 'string', description: '要删除的订阅源地址(可选,与 name 至少给一个)。' },
|
|
467
467
|
name: { type: 'string', description: '要删除的订阅显示名(可选,与 url 至少给一个;同名全部删除)。' },
|
|
@@ -641,7 +641,7 @@ export function buildRssTools(config, settingsScope, fetchImpl, lookupImpl) {
|
|
|
641
641
|
const nameFilter = optionalString(args, 'name');
|
|
642
642
|
let targets = getFeeds();
|
|
643
643
|
if (urlFilter !== undefined)
|
|
644
|
-
targets = targets.filter((feed) => feed.url
|
|
644
|
+
targets = targets.filter((feed) => sameFeedUrl(feed.url, urlFilter));
|
|
645
645
|
if (nameFilter !== undefined)
|
|
646
646
|
targets = findFeedsByName(targets, nameFilter);
|
|
647
647
|
if (targets.length === 0) {
|