@nahisaho/katashiro-collector 0.1.13 → 0.2.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/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/source/credibility-scorer.d.ts +94 -0
- package/dist/source/credibility-scorer.d.ts.map +1 -0
- package/dist/source/credibility-scorer.js +240 -0
- package/dist/source/credibility-scorer.js.map +1 -0
- package/dist/source/index.d.ts +9 -0
- package/dist/source/index.d.ts.map +1 -0
- package/dist/source/index.js +9 -0
- package/dist/source/index.js.map +1 -0
- package/dist/source/source-tracker.d.ts +121 -0
- package/dist/source/source-tracker.d.ts.map +1 -0
- package/dist/source/source-tracker.js +197 -0
- package/dist/source/source-tracker.js.map +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -15,4 +15,5 @@ export { FeedReader } from './feed/index.js';
|
|
|
15
15
|
export { APIClient, type APIClientOptions } from './api/index.js';
|
|
16
16
|
export { MediaExtractor, type ExtractedMedia } from './media/index.js';
|
|
17
17
|
export { APIClient as ApiClient } from './api/index.js';
|
|
18
|
+
export { SourceTracker, type TrackedSource, type SourceMetadata, CredibilityScorer, type CredibilityFactors, type CredibilityScore, } from './source/index.js';
|
|
18
19
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,eAAe,GAChB,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,QAAQ,EACR,iBAAiB,EACjB,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGvE,OAAO,EAAE,SAAS,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,eAAe,GAChB,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,QAAQ,EACR,iBAAiB,EACjB,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGvE,OAAO,EAAE,SAAS,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGxD,OAAO,EACL,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -15,4 +15,6 @@ export { APIClient } from './api/index.js';
|
|
|
15
15
|
export { MediaExtractor } from './media/index.js';
|
|
16
16
|
// AGENTS.md互換エイリアス(APIClientをApiClientとしてもエクスポート)
|
|
17
17
|
export { APIClient as ApiClient } from './api/index.js';
|
|
18
|
+
// Source tracking (v0.2.0)
|
|
19
|
+
export { SourceTracker, CredibilityScorer, } from './source/index.js';
|
|
18
20
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAsBH,KAAK;AACL,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAyB,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAuB,MAAM,kBAAkB,CAAC;AAEvE,kDAAkD;AAClD,OAAO,EAAE,SAAS,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAsBH,KAAK;AACL,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAyB,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAuB,MAAM,kBAAkB,CAAC;AAEvE,kDAAkD;AAClD,OAAO,EAAE,SAAS,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAExD,2BAA2B;AAC3B,OAAO,EACL,aAAa,EAGb,iBAAiB,GAGlB,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CredibilityScorer - ソース信頼度スコアリング
|
|
3
|
+
*
|
|
4
|
+
* @since 0.2.0
|
|
5
|
+
* @requirement REQ-COLLECT-007-ENH-002
|
|
6
|
+
* @design DES-KATASHIRO-002 §4.6.3 信頼度スコアリングアルゴリズム
|
|
7
|
+
*/
|
|
8
|
+
import type { TrackedSource } from './source-tracker.js';
|
|
9
|
+
/**
|
|
10
|
+
* 信頼度計算要素
|
|
11
|
+
*/
|
|
12
|
+
export interface CredibilityFactors {
|
|
13
|
+
/** ドメイン評価 (0-90) */
|
|
14
|
+
domainReputation: number;
|
|
15
|
+
/** HTTPS使用ボーナス (0 or 5) */
|
|
16
|
+
httpsBonus: number;
|
|
17
|
+
/** 著者ボーナス (0 or 10) */
|
|
18
|
+
authorBonus: number;
|
|
19
|
+
/** 被引用ボーナス (0-20) */
|
|
20
|
+
citationBonus: number;
|
|
21
|
+
/** 古さペナルティ (0 to -30) */
|
|
22
|
+
recencyPenalty: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 信頼度スコア結果
|
|
26
|
+
*/
|
|
27
|
+
export interface CredibilityScore {
|
|
28
|
+
/** 総合スコア (0-100) */
|
|
29
|
+
total: number;
|
|
30
|
+
/** 各要素の内訳 */
|
|
31
|
+
factors: CredibilityFactors;
|
|
32
|
+
/** スコアの説明 */
|
|
33
|
+
explanation: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 信頼度スコアリングクラス
|
|
37
|
+
*/
|
|
38
|
+
export declare class CredibilityScorer {
|
|
39
|
+
/** カスタムドメイン評価 */
|
|
40
|
+
private customDomainScores;
|
|
41
|
+
/** 登録済み専門家 */
|
|
42
|
+
private knownAuthors;
|
|
43
|
+
/** ドメインカテゴリ定義 */
|
|
44
|
+
private static readonly DOMAIN_CATEGORIES;
|
|
45
|
+
/**
|
|
46
|
+
* ソースの信頼度をスコアリング
|
|
47
|
+
*/
|
|
48
|
+
score(source: TrackedSource): Promise<CredibilityScore>;
|
|
49
|
+
/**
|
|
50
|
+
* 各要素を計算
|
|
51
|
+
*/
|
|
52
|
+
private calculateFactors;
|
|
53
|
+
/**
|
|
54
|
+
* ドメインスコアを取得
|
|
55
|
+
*/
|
|
56
|
+
private getDomainScore;
|
|
57
|
+
/**
|
|
58
|
+
* 著者ボーナスを取得
|
|
59
|
+
*/
|
|
60
|
+
private getAuthorBonus;
|
|
61
|
+
/**
|
|
62
|
+
* 古さペナルティを計算
|
|
63
|
+
*/
|
|
64
|
+
private calculateRecencyPenalty;
|
|
65
|
+
/**
|
|
66
|
+
* 総合スコアを計算
|
|
67
|
+
*/
|
|
68
|
+
private calculateTotal;
|
|
69
|
+
/**
|
|
70
|
+
* スコアの説明を生成
|
|
71
|
+
*/
|
|
72
|
+
private generateExplanation;
|
|
73
|
+
/**
|
|
74
|
+
* カスタムドメイン評価を設定
|
|
75
|
+
*/
|
|
76
|
+
setDomainReputation(domain: string, score: number): void;
|
|
77
|
+
/**
|
|
78
|
+
* ドメイン評価を削除
|
|
79
|
+
*/
|
|
80
|
+
removeDomainReputation(domain: string): void;
|
|
81
|
+
/**
|
|
82
|
+
* 専門家を登録
|
|
83
|
+
*/
|
|
84
|
+
addKnownAuthor(authorName: string, expertise: string[]): void;
|
|
85
|
+
/**
|
|
86
|
+
* 専門家を削除
|
|
87
|
+
*/
|
|
88
|
+
removeKnownAuthor(authorName: string): void;
|
|
89
|
+
/**
|
|
90
|
+
* 登録済み専門家リストを取得
|
|
91
|
+
*/
|
|
92
|
+
getKnownAuthors(): Map<string, string[]>;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=credibility-scorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credibility-scorer.d.ts","sourceRoot":"","sources":["../../src/source/credibility-scorer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,oBAAoB;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,2BAA2B;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,uBAAuB;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,yBAAyB;IACzB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa;IACb,OAAO,EAAE,kBAAkB,CAAC;IAC5B,aAAa;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAWD;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,iBAAiB;IACjB,OAAO,CAAC,kBAAkB,CAAkC;IAC5D,cAAc;IACd,OAAO,CAAC,YAAY,CAAoC;IAExD,iBAAiB;IACjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAmEvC;IAEF;;OAEG;IACG,KAAK,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAY7D;;OAEG;YACW,gBAAgB;IA+B9B;;OAEG;IACH,OAAO,CAAC,cAAc;IAwBtB;;OAEG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAa/B;;OAEG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAqB3B;;OAEG;IACH,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIxD;;OAEG;IACH,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI5C;;OAEG;IACH,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IAI7D;;OAEG;IACH,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAI3C;;OAEG;IACH,eAAe,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;CAGzC"}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CredibilityScorer - ソース信頼度スコアリング
|
|
3
|
+
*
|
|
4
|
+
* @since 0.2.0
|
|
5
|
+
* @requirement REQ-COLLECT-007-ENH-002
|
|
6
|
+
* @design DES-KATASHIRO-002 §4.6.3 信頼度スコアリングアルゴリズム
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* 信頼度スコアリングクラス
|
|
10
|
+
*/
|
|
11
|
+
export class CredibilityScorer {
|
|
12
|
+
/** カスタムドメイン評価 */
|
|
13
|
+
customDomainScores = new Map();
|
|
14
|
+
/** 登録済み専門家 */
|
|
15
|
+
knownAuthors = new Map();
|
|
16
|
+
/** ドメインカテゴリ定義 */
|
|
17
|
+
static DOMAIN_CATEGORIES = [
|
|
18
|
+
{
|
|
19
|
+
label: 'Academic/Research',
|
|
20
|
+
score: 90,
|
|
21
|
+
patterns: [
|
|
22
|
+
/\.edu$/,
|
|
23
|
+
/\.ac\.[a-z]{2}$/,
|
|
24
|
+
/arxiv\.org$/,
|
|
25
|
+
/nature\.com$/,
|
|
26
|
+
/science\.org$/,
|
|
27
|
+
/springer\.com$/,
|
|
28
|
+
/wiley\.com$/,
|
|
29
|
+
/acm\.org$/,
|
|
30
|
+
/ieee\.org$/,
|
|
31
|
+
/pubmed\.gov$/,
|
|
32
|
+
/scholar\.google/,
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
label: 'Government/Official',
|
|
37
|
+
score: 85,
|
|
38
|
+
patterns: [
|
|
39
|
+
/\.gov$/,
|
|
40
|
+
/\.gov\.[a-z]{2}$/,
|
|
41
|
+
/\.go\.jp$/,
|
|
42
|
+
/\.gc\.ca$/,
|
|
43
|
+
/who\.int$/,
|
|
44
|
+
/un\.org$/,
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
label: 'Major News/Wire',
|
|
49
|
+
score: 75,
|
|
50
|
+
patterns: [
|
|
51
|
+
/reuters\.com$/,
|
|
52
|
+
/apnews\.com$/,
|
|
53
|
+
/bbc\.com$/,
|
|
54
|
+
/bbc\.co\.uk$/,
|
|
55
|
+
/nytimes\.com$/,
|
|
56
|
+
/wsj\.com$/,
|
|
57
|
+
/theguardian\.com$/,
|
|
58
|
+
/nikkei\.com$/,
|
|
59
|
+
/nhk\.or\.jp$/,
|
|
60
|
+
/asahi\.com$/,
|
|
61
|
+
/mainichi\.jp$/,
|
|
62
|
+
/yomiuri\.co\.jp$/,
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
label: 'Tech Platforms',
|
|
67
|
+
score: 50,
|
|
68
|
+
patterns: [
|
|
69
|
+
/medium\.com$/,
|
|
70
|
+
/qiita\.com$/,
|
|
71
|
+
/zenn\.dev$/,
|
|
72
|
+
/note\.com$/,
|
|
73
|
+
/dev\.to$/,
|
|
74
|
+
/hashnode\.dev$/,
|
|
75
|
+
/stackoverflow\.com$/,
|
|
76
|
+
/github\.com$/,
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
label: 'Default',
|
|
81
|
+
score: 40,
|
|
82
|
+
patterns: [],
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
/**
|
|
86
|
+
* ソースの信頼度をスコアリング
|
|
87
|
+
*/
|
|
88
|
+
async score(source) {
|
|
89
|
+
const factors = await this.calculateFactors(source);
|
|
90
|
+
const total = this.calculateTotal(factors);
|
|
91
|
+
const explanation = this.generateExplanation(factors, total);
|
|
92
|
+
return {
|
|
93
|
+
total,
|
|
94
|
+
factors,
|
|
95
|
+
explanation,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 各要素を計算
|
|
100
|
+
*/
|
|
101
|
+
async calculateFactors(source) {
|
|
102
|
+
const domain = source.metadata.domain;
|
|
103
|
+
const url = source.url;
|
|
104
|
+
const author = source.metadata.author;
|
|
105
|
+
const publishedAt = source.metadata.publishedAt;
|
|
106
|
+
const citationCount = source.usedIn.length;
|
|
107
|
+
// ドメイン評価
|
|
108
|
+
const domainReputation = this.getDomainScore(domain);
|
|
109
|
+
// HTTPSボーナス
|
|
110
|
+
const httpsBonus = url.startsWith('https://') ? 5 : 0;
|
|
111
|
+
// 著者ボーナス
|
|
112
|
+
const authorBonus = this.getAuthorBonus(author);
|
|
113
|
+
// 被引用ボーナス
|
|
114
|
+
const citationBonus = Math.min(citationCount * 1, 20);
|
|
115
|
+
// 古さペナルティ
|
|
116
|
+
const recencyPenalty = this.calculateRecencyPenalty(publishedAt);
|
|
117
|
+
return {
|
|
118
|
+
domainReputation,
|
|
119
|
+
httpsBonus,
|
|
120
|
+
authorBonus,
|
|
121
|
+
citationBonus,
|
|
122
|
+
recencyPenalty,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* ドメインスコアを取得
|
|
127
|
+
*/
|
|
128
|
+
getDomainScore(domain) {
|
|
129
|
+
// カスタム設定をチェック
|
|
130
|
+
const customScore = this.customDomainScores.get(domain);
|
|
131
|
+
if (customScore !== undefined) {
|
|
132
|
+
return customScore;
|
|
133
|
+
}
|
|
134
|
+
// カテゴリマッチング
|
|
135
|
+
for (const category of CredibilityScorer.DOMAIN_CATEGORIES) {
|
|
136
|
+
for (const pattern of category.patterns) {
|
|
137
|
+
if (typeof pattern === 'string') {
|
|
138
|
+
if (domain === pattern || domain.endsWith(pattern)) {
|
|
139
|
+
return category.score;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else if (pattern.test(domain)) {
|
|
143
|
+
return category.score;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// デフォルトスコア
|
|
148
|
+
return 40;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* 著者ボーナスを取得
|
|
152
|
+
*/
|
|
153
|
+
getAuthorBonus(author) {
|
|
154
|
+
if (!author)
|
|
155
|
+
return 0;
|
|
156
|
+
// 登録済み専門家かチェック
|
|
157
|
+
if (this.knownAuthors.has(author)) {
|
|
158
|
+
return 10;
|
|
159
|
+
}
|
|
160
|
+
// 著者名があるだけでも小さなボーナス
|
|
161
|
+
return 3;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* 古さペナルティを計算
|
|
165
|
+
*/
|
|
166
|
+
calculateRecencyPenalty(publishedAt) {
|
|
167
|
+
if (!publishedAt)
|
|
168
|
+
return 0; // 日付不明は0
|
|
169
|
+
const now = new Date();
|
|
170
|
+
const yearDiff = now.getFullYear() - publishedAt.getFullYear();
|
|
171
|
+
// 2年以内は0
|
|
172
|
+
if (yearDiff <= 2)
|
|
173
|
+
return 0;
|
|
174
|
+
// 2年を超えると年ごとに-5、最大-30
|
|
175
|
+
return Math.max((yearDiff - 2) * -5, -30);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* 総合スコアを計算
|
|
179
|
+
*/
|
|
180
|
+
calculateTotal(factors) {
|
|
181
|
+
const total = factors.domainReputation +
|
|
182
|
+
factors.httpsBonus +
|
|
183
|
+
factors.authorBonus +
|
|
184
|
+
factors.citationBonus +
|
|
185
|
+
factors.recencyPenalty;
|
|
186
|
+
// 0-100にクランプ
|
|
187
|
+
return Math.max(0, Math.min(100, total));
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* スコアの説明を生成
|
|
191
|
+
*/
|
|
192
|
+
generateExplanation(factors, total) {
|
|
193
|
+
const parts = [];
|
|
194
|
+
parts.push(`Domain: ${factors.domainReputation}`);
|
|
195
|
+
if (factors.httpsBonus > 0) {
|
|
196
|
+
parts.push(`HTTPS: +${factors.httpsBonus}`);
|
|
197
|
+
}
|
|
198
|
+
if (factors.authorBonus > 0) {
|
|
199
|
+
parts.push(`Author: +${factors.authorBonus}`);
|
|
200
|
+
}
|
|
201
|
+
if (factors.citationBonus > 0) {
|
|
202
|
+
parts.push(`Citations: +${factors.citationBonus}`);
|
|
203
|
+
}
|
|
204
|
+
if (factors.recencyPenalty < 0) {
|
|
205
|
+
parts.push(`Age: ${factors.recencyPenalty}`);
|
|
206
|
+
}
|
|
207
|
+
return `Total: ${total}/100 (${parts.join(', ')})`;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* カスタムドメイン評価を設定
|
|
211
|
+
*/
|
|
212
|
+
setDomainReputation(domain, score) {
|
|
213
|
+
this.customDomainScores.set(domain, Math.max(0, Math.min(100, score)));
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* ドメイン評価を削除
|
|
217
|
+
*/
|
|
218
|
+
removeDomainReputation(domain) {
|
|
219
|
+
this.customDomainScores.delete(domain);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* 専門家を登録
|
|
223
|
+
*/
|
|
224
|
+
addKnownAuthor(authorName, expertise) {
|
|
225
|
+
this.knownAuthors.set(authorName, expertise);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* 専門家を削除
|
|
229
|
+
*/
|
|
230
|
+
removeKnownAuthor(authorName) {
|
|
231
|
+
this.knownAuthors.delete(authorName);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* 登録済み専門家リストを取得
|
|
235
|
+
*/
|
|
236
|
+
getKnownAuthors() {
|
|
237
|
+
return new Map(this.knownAuthors);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=credibility-scorer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credibility-scorer.js","sourceRoot":"","sources":["../../src/source/credibility-scorer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source tracking and credibility scoring
|
|
3
|
+
* @since 0.2.0
|
|
4
|
+
* @requirement REQ-COLLECT-007-ENH
|
|
5
|
+
* @design DES-KATASHIRO-002 §4.6 ソース追跡強化
|
|
6
|
+
*/
|
|
7
|
+
export { SourceTracker, type TrackedSource, type SourceMetadata, } from './source-tracker.js';
|
|
8
|
+
export { CredibilityScorer, type CredibilityFactors, type CredibilityScore, } from './credibility-scorer.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/source/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source tracking and credibility scoring
|
|
3
|
+
* @since 0.2.0
|
|
4
|
+
* @requirement REQ-COLLECT-007-ENH
|
|
5
|
+
* @design DES-KATASHIRO-002 §4.6 ソース追跡強化
|
|
6
|
+
*/
|
|
7
|
+
export { SourceTracker, } from './source-tracker.js';
|
|
8
|
+
export { CredibilityScorer, } from './credibility-scorer.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/source/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,aAAa,GAGd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,iBAAiB,GAGlB,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SourceTracker - ソース追跡・変更検出
|
|
3
|
+
*
|
|
4
|
+
* @since 0.2.0
|
|
5
|
+
* @requirement REQ-COLLECT-007-ENH-001
|
|
6
|
+
* @design DES-KATASHIRO-002 §4.6 ソース追跡強化
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* ソースメタデータ
|
|
10
|
+
*/
|
|
11
|
+
export interface SourceMetadata {
|
|
12
|
+
/** タイトル */
|
|
13
|
+
title?: string;
|
|
14
|
+
/** 著者 */
|
|
15
|
+
author?: string;
|
|
16
|
+
/** 公開日 */
|
|
17
|
+
publishedAt?: Date;
|
|
18
|
+
/** ドメイン */
|
|
19
|
+
domain: string;
|
|
20
|
+
/** 追加メタデータ */
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 追跡されたソース
|
|
25
|
+
*/
|
|
26
|
+
export interface TrackedSource {
|
|
27
|
+
/** 一意識別子 */
|
|
28
|
+
id: string;
|
|
29
|
+
/** URL */
|
|
30
|
+
url: string;
|
|
31
|
+
/** アクセス日時 */
|
|
32
|
+
accessedAt: Date;
|
|
33
|
+
/** コンテンツハッシュ (SHA-256) */
|
|
34
|
+
contentHash: string;
|
|
35
|
+
/** 信頼度スコア (0-100) */
|
|
36
|
+
credibilityScore: number;
|
|
37
|
+
/** メタデータ */
|
|
38
|
+
metadata: SourceMetadata;
|
|
39
|
+
/** 使用されたコンテンツIDリスト */
|
|
40
|
+
usedIn: string[];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* ソース追跡クラス
|
|
44
|
+
*/
|
|
45
|
+
export declare class SourceTracker {
|
|
46
|
+
/** インメモリストア */
|
|
47
|
+
private sources;
|
|
48
|
+
/** URLからIDへのマッピング */
|
|
49
|
+
private urlIndex;
|
|
50
|
+
/** ハッシュからIDへのマッピング */
|
|
51
|
+
private hashIndex;
|
|
52
|
+
/**
|
|
53
|
+
* ソースを追跡
|
|
54
|
+
*/
|
|
55
|
+
track(url: string, content: string): Promise<TrackedSource>;
|
|
56
|
+
/**
|
|
57
|
+
* URLでソースを取得
|
|
58
|
+
*/
|
|
59
|
+
getByUrl(url: string): Promise<TrackedSource | null>;
|
|
60
|
+
/**
|
|
61
|
+
* ハッシュでソースを取得
|
|
62
|
+
*/
|
|
63
|
+
getByHash(hash: string): Promise<TrackedSource | null>;
|
|
64
|
+
/**
|
|
65
|
+
* IDでソースを取得
|
|
66
|
+
*/
|
|
67
|
+
getById(id: string): Promise<TrackedSource | null>;
|
|
68
|
+
/**
|
|
69
|
+
* ソースをコンテンツに紐付け
|
|
70
|
+
*/
|
|
71
|
+
linkToContent(sourceId: string, contentId: string): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* コンテンツIDからソースを逆引き
|
|
74
|
+
*/
|
|
75
|
+
getSourcesByContent(contentId: string): Promise<TrackedSource[]>;
|
|
76
|
+
/**
|
|
77
|
+
* コンテンツ変更を検出
|
|
78
|
+
*/
|
|
79
|
+
detectChange(url: string, newContent: string): Promise<boolean>;
|
|
80
|
+
/**
|
|
81
|
+
* メタデータを更新
|
|
82
|
+
*/
|
|
83
|
+
updateMetadata(sourceId: string, metadata: Partial<SourceMetadata>): Promise<TrackedSource | null>;
|
|
84
|
+
/**
|
|
85
|
+
* 信頼度スコアを設定
|
|
86
|
+
*/
|
|
87
|
+
setCredibilityScore(sourceId: string, score: number): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* すべてのソースを取得
|
|
90
|
+
*/
|
|
91
|
+
getAll(): Promise<TrackedSource[]>;
|
|
92
|
+
/**
|
|
93
|
+
* ソース数を取得
|
|
94
|
+
*/
|
|
95
|
+
get size(): number;
|
|
96
|
+
/**
|
|
97
|
+
* エクスポート(永続化用)
|
|
98
|
+
*/
|
|
99
|
+
export(): TrackedSource[];
|
|
100
|
+
/**
|
|
101
|
+
* インポート(復元用)
|
|
102
|
+
*/
|
|
103
|
+
import(sources: TrackedSource[]): void;
|
|
104
|
+
/**
|
|
105
|
+
* クリア
|
|
106
|
+
*/
|
|
107
|
+
clear(): void;
|
|
108
|
+
/**
|
|
109
|
+
* SHA-256ハッシュを計算
|
|
110
|
+
*/
|
|
111
|
+
private computeHash;
|
|
112
|
+
/**
|
|
113
|
+
* ドメインを抽出
|
|
114
|
+
*/
|
|
115
|
+
private extractDomain;
|
|
116
|
+
/**
|
|
117
|
+
* 一意IDを生成
|
|
118
|
+
*/
|
|
119
|
+
private generateId;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=source-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-tracker.d.ts","sourceRoot":"","sources":["../../src/source/source-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS;IACT,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU;IACV,WAAW,CAAC,EAAE,IAAI,CAAC;IACnB,WAAW;IACX,MAAM,EAAE,MAAM,CAAC;IACf,cAAc;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,YAAY;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,UAAU;IACV,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa;IACb,UAAU,EAAE,IAAI,CAAC;IACjB,0BAA0B;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY;IACZ,QAAQ,EAAE,cAAc,CAAC;IACzB,sBAAsB;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,eAAe;IACf,OAAO,CAAC,OAAO,CAAyC;IACxD,qBAAqB;IACrB,OAAO,CAAC,QAAQ,CAAkC;IAClD,sBAAsB;IACtB,OAAO,CAAC,SAAS,CAAkC;IAEnD;;OAEG;IACG,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAyCjE;;OAEG;IACG,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAM1D;;OAEG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAM5D;;OAEG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAIxD;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvE;;OAEG;IACG,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAUtE;;OAEG;IACG,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASrE;;OAEG;IACG,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,GAChC,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAWhC;;OAEG;IACG,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOzE;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAIxC;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,MAAM,IAAI,aAAa,EAAE;IAIzB;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,IAAI;IAQtC;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,OAAO,CAAC,aAAa;IASrB;;OAEG;IACH,OAAO,CAAC,UAAU;CAGnB"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SourceTracker - ソース追跡・変更検出
|
|
3
|
+
*
|
|
4
|
+
* @since 0.2.0
|
|
5
|
+
* @requirement REQ-COLLECT-007-ENH-001
|
|
6
|
+
* @design DES-KATASHIRO-002 §4.6 ソース追跡強化
|
|
7
|
+
*/
|
|
8
|
+
import { createHash } from 'node:crypto';
|
|
9
|
+
/**
|
|
10
|
+
* ソース追跡クラス
|
|
11
|
+
*/
|
|
12
|
+
export class SourceTracker {
|
|
13
|
+
/** インメモリストア */
|
|
14
|
+
sources = new Map();
|
|
15
|
+
/** URLからIDへのマッピング */
|
|
16
|
+
urlIndex = new Map();
|
|
17
|
+
/** ハッシュからIDへのマッピング */
|
|
18
|
+
hashIndex = new Map();
|
|
19
|
+
/**
|
|
20
|
+
* ソースを追跡
|
|
21
|
+
*/
|
|
22
|
+
async track(url, content) {
|
|
23
|
+
const contentHash = this.computeHash(content);
|
|
24
|
+
const domain = this.extractDomain(url);
|
|
25
|
+
// 既存チェック
|
|
26
|
+
const existingId = this.urlIndex.get(url);
|
|
27
|
+
if (existingId) {
|
|
28
|
+
const existing = this.sources.get(existingId);
|
|
29
|
+
if (existing) {
|
|
30
|
+
// コンテンツが変更されたか確認
|
|
31
|
+
if (existing.contentHash !== contentHash) {
|
|
32
|
+
// 変更あり - 更新
|
|
33
|
+
existing.contentHash = contentHash;
|
|
34
|
+
existing.accessedAt = new Date();
|
|
35
|
+
this.hashIndex.set(contentHash, existingId);
|
|
36
|
+
}
|
|
37
|
+
return existing;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// 新規作成
|
|
41
|
+
const id = this.generateId();
|
|
42
|
+
const trackedSource = {
|
|
43
|
+
id,
|
|
44
|
+
url,
|
|
45
|
+
accessedAt: new Date(),
|
|
46
|
+
contentHash,
|
|
47
|
+
credibilityScore: 0, // 後でCredibilityScorerで計算
|
|
48
|
+
metadata: {
|
|
49
|
+
domain,
|
|
50
|
+
},
|
|
51
|
+
usedIn: [],
|
|
52
|
+
};
|
|
53
|
+
this.sources.set(id, trackedSource);
|
|
54
|
+
this.urlIndex.set(url, id);
|
|
55
|
+
this.hashIndex.set(contentHash, id);
|
|
56
|
+
return trackedSource;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* URLでソースを取得
|
|
60
|
+
*/
|
|
61
|
+
async getByUrl(url) {
|
|
62
|
+
const id = this.urlIndex.get(url);
|
|
63
|
+
if (!id)
|
|
64
|
+
return null;
|
|
65
|
+
return this.sources.get(id) || null;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* ハッシュでソースを取得
|
|
69
|
+
*/
|
|
70
|
+
async getByHash(hash) {
|
|
71
|
+
const id = this.hashIndex.get(hash);
|
|
72
|
+
if (!id)
|
|
73
|
+
return null;
|
|
74
|
+
return this.sources.get(id) || null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* IDでソースを取得
|
|
78
|
+
*/
|
|
79
|
+
async getById(id) {
|
|
80
|
+
return this.sources.get(id) || null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* ソースをコンテンツに紐付け
|
|
84
|
+
*/
|
|
85
|
+
async linkToContent(sourceId, contentId) {
|
|
86
|
+
const source = this.sources.get(sourceId);
|
|
87
|
+
if (source && !source.usedIn.includes(contentId)) {
|
|
88
|
+
source.usedIn.push(contentId);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* コンテンツIDからソースを逆引き
|
|
93
|
+
*/
|
|
94
|
+
async getSourcesByContent(contentId) {
|
|
95
|
+
const results = [];
|
|
96
|
+
for (const source of this.sources.values()) {
|
|
97
|
+
if (source.usedIn.includes(contentId)) {
|
|
98
|
+
results.push(source);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return results;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* コンテンツ変更を検出
|
|
105
|
+
*/
|
|
106
|
+
async detectChange(url, newContent) {
|
|
107
|
+
const existing = await this.getByUrl(url);
|
|
108
|
+
if (!existing) {
|
|
109
|
+
return true; // 新規は「変更あり」扱い
|
|
110
|
+
}
|
|
111
|
+
const newHash = this.computeHash(newContent);
|
|
112
|
+
return existing.contentHash !== newHash;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* メタデータを更新
|
|
116
|
+
*/
|
|
117
|
+
async updateMetadata(sourceId, metadata) {
|
|
118
|
+
const source = this.sources.get(sourceId);
|
|
119
|
+
if (!source)
|
|
120
|
+
return null;
|
|
121
|
+
source.metadata = {
|
|
122
|
+
...source.metadata,
|
|
123
|
+
...metadata,
|
|
124
|
+
};
|
|
125
|
+
return source;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* 信頼度スコアを設定
|
|
129
|
+
*/
|
|
130
|
+
async setCredibilityScore(sourceId, score) {
|
|
131
|
+
const source = this.sources.get(sourceId);
|
|
132
|
+
if (source) {
|
|
133
|
+
source.credibilityScore = Math.max(0, Math.min(100, score));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* すべてのソースを取得
|
|
138
|
+
*/
|
|
139
|
+
async getAll() {
|
|
140
|
+
return Array.from(this.sources.values());
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* ソース数を取得
|
|
144
|
+
*/
|
|
145
|
+
get size() {
|
|
146
|
+
return this.sources.size;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* エクスポート(永続化用)
|
|
150
|
+
*/
|
|
151
|
+
export() {
|
|
152
|
+
return Array.from(this.sources.values());
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* インポート(復元用)
|
|
156
|
+
*/
|
|
157
|
+
import(sources) {
|
|
158
|
+
for (const source of sources) {
|
|
159
|
+
this.sources.set(source.id, source);
|
|
160
|
+
this.urlIndex.set(source.url, source.id);
|
|
161
|
+
this.hashIndex.set(source.contentHash, source.id);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* クリア
|
|
166
|
+
*/
|
|
167
|
+
clear() {
|
|
168
|
+
this.sources.clear();
|
|
169
|
+
this.urlIndex.clear();
|
|
170
|
+
this.hashIndex.clear();
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* SHA-256ハッシュを計算
|
|
174
|
+
*/
|
|
175
|
+
computeHash(content) {
|
|
176
|
+
return createHash('sha256').update(content, 'utf8').digest('hex');
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* ドメインを抽出
|
|
180
|
+
*/
|
|
181
|
+
extractDomain(url) {
|
|
182
|
+
try {
|
|
183
|
+
const parsed = new URL(url);
|
|
184
|
+
return parsed.hostname;
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return 'unknown';
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* 一意IDを生成
|
|
192
|
+
*/
|
|
193
|
+
generateId() {
|
|
194
|
+
return `src-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=source-tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-tracker.js","sourceRoot":"","sources":["../../src/source/source-tracker.ts"],"names":[],"mappings":"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"}
|