recallnest 2.2.1 → 2.5.4
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 +150 -0
- package/README.md +46 -35
- package/README_CN.md +41 -26
- package/assets/ui/app.js +1031 -0
- package/assets/ui/index.html +224 -0
- package/assets/ui/styles.css +781 -0
- package/config.json.example +4 -1
- package/connectors/examples/email-adapter.ts +73 -0
- package/connectors/examples/logs-adapter.ts +103 -0
- package/connectors/examples/rss-adapter.ts +95 -0
- package/docs/api-reference.md +1291 -0
- package/docs/architecture.md +168 -0
- package/docs/connector-spec.md +126 -0
- package/eval/cases-canary.json +58 -0
- package/eval/cases-scope-robustness.json +278 -0
- package/eval/cases.json +117 -20
- package/package.json +22 -1
- package/src/__tests__/access-tracker-novelty.test.ts +238 -0
- package/src/__tests__/activity-counter.test.ts +125 -0
- package/src/__tests__/adaptive-fidelity.test.ts +102 -0
- package/src/__tests__/admission-control.test.ts +206 -0
- package/src/__tests__/anchor-generator.test.ts +67 -0
- package/src/__tests__/auto-consolidation.test.ts +168 -0
- package/src/__tests__/auto-recall.test.ts +131 -0
- package/src/__tests__/babel-integration.test.ts +144 -0
- package/src/__tests__/batch-dedup.test.ts +65 -0
- package/src/__tests__/canary-eval.test.ts +114 -0
- package/src/__tests__/capture-engine.test.ts +1238 -0
- package/src/__tests__/capture-heuristic.test.ts +171 -0
- package/src/__tests__/cascade-forget.test.ts +210 -0
- package/src/__tests__/category-min-scores.test.ts +33 -0
- package/src/__tests__/cc8-cc1-essential-context.test.ts +298 -0
- package/src/__tests__/circuit-breaker.test.ts +99 -0
- package/src/__tests__/cluster-consolidation.test.ts +782 -0
- package/src/__tests__/confidence-metadata.test.ts +125 -0
- package/src/__tests__/confidence-tracker.test.ts +261 -0
- package/src/__tests__/conflict-advisor.test.ts +206 -0
- package/src/__tests__/conflict-escalation.test.ts +149 -0
- package/src/__tests__/conflict-lifecycle.test.ts +83 -0
- package/src/__tests__/conflict-output.test.ts +85 -0
- package/src/__tests__/conflict-store.test.ts +374 -0
- package/src/__tests__/connector-v1.test.ts +181 -0
- package/src/__tests__/consolidation-engine.test.ts +333 -0
- package/src/__tests__/constructive-retrieval.test.ts +509 -0
- package/src/__tests__/context-collapse-renderer.test.ts +214 -0
- package/src/__tests__/context-composer-pins.test.ts +64 -0
- package/src/__tests__/context-composer-task-selection.test.ts +24 -0
- package/src/__tests__/context-reconstructor.test.ts +65 -0
- package/src/__tests__/context-renderer.test.ts +91 -0
- package/src/__tests__/continuity-eval.test.ts +275 -0
- package/src/__tests__/continuity-schema.test.ts +97 -0
- package/src/__tests__/contracts.test.ts +216 -0
- package/src/__tests__/conversation-importer.test.ts +692 -0
- package/src/__tests__/core-recall-eval.test.ts +235 -0
- package/src/__tests__/core-summary.test.ts +109 -0
- package/src/__tests__/data-checkup.test.ts +276 -0
- package/src/__tests__/decay-exemption.test.ts +84 -0
- package/src/__tests__/dedup-actions.test.ts +58 -0
- package/src/__tests__/dedup-guard.test.ts +39 -0
- package/src/__tests__/deterministic-id.test.ts +39 -0
- package/src/__tests__/distill-lock.test.ts +305 -0
- package/src/__tests__/distill-session-argshape.test.ts +79 -0
- package/src/__tests__/doctor.test.ts +319 -0
- package/src/__tests__/dream-pipeline.test.ts +321 -0
- package/src/__tests__/drill-down.test.ts +108 -0
- package/src/__tests__/embedder.test.ts +122 -0
- package/src/__tests__/emotion-decay.test.ts +46 -0
- package/src/__tests__/emotion-detector.test.ts +56 -0
- package/src/__tests__/emotion-phase1-integration.test.ts +153 -0
- package/src/__tests__/emotion-retrieval.test.ts +56 -0
- package/src/__tests__/entity-resolver.test.ts +58 -0
- package/src/__tests__/env-config.test.ts +151 -0
- package/src/__tests__/error-signature-boost.test.ts +87 -0
- package/src/__tests__/error-signature.test.ts +95 -0
- package/src/__tests__/error-taxonomy.test.ts +129 -0
- package/src/__tests__/ethics-layer.test.ts +476 -0
- package/src/__tests__/event-segmenter.test.ts +153 -0
- package/src/__tests__/feature-flags-integration.test.ts +54 -0
- package/src/__tests__/frequency-tracker.test.ts +113 -0
- package/src/__tests__/graph-export.test.ts +489 -0
- package/src/__tests__/hotness-blend.test.ts +76 -0
- package/src/__tests__/ingest-chunking.test.ts +44 -0
- package/src/__tests__/ingest.test.ts +360 -0
- package/src/__tests__/interference-detector.test.ts +203 -0
- package/src/__tests__/kg-extractor.test.ts +192 -0
- package/src/__tests__/kg-store.test.ts +300 -0
- package/src/__tests__/llm-consolidation.test.ts +226 -0
- package/src/__tests__/maintenance-locks.test.ts +174 -0
- package/src/__tests__/mcp-efficiency.test.ts +288 -0
- package/src/__tests__/mcp-related-scopes.test.ts +151 -0
- package/src/__tests__/memory-boundaries.test.ts +250 -0
- package/src/__tests__/memory-evolution-b2-b3-e1.test.ts +345 -0
- package/src/__tests__/memory-evolution.test.ts +271 -0
- package/src/__tests__/memory-health-rebalance.test.ts +144 -0
- package/src/__tests__/memory-lint.test.ts +421 -0
- package/src/__tests__/memory-output.test.ts +215 -0
- package/src/__tests__/memory-promotion.test.ts +315 -0
- package/src/__tests__/migrate-dedup-ids.test.ts +65 -0
- package/src/__tests__/multi-vector.test.ts +242 -0
- package/src/__tests__/narrative-architecture.test.ts +456 -0
- package/src/__tests__/noise-filter.test.ts +205 -0
- package/src/__tests__/obsidian-connector.test.ts +363 -0
- package/src/__tests__/omitted-reporting.test.ts +98 -0
- package/src/__tests__/pending-review.test.ts +77 -0
- package/src/__tests__/pii-redact.test.ts +314 -0
- package/src/__tests__/post-retrieval-filter.test.ts +178 -0
- package/src/__tests__/ppr-traversal.test.ts +256 -0
- package/src/__tests__/prediction-engine.test.ts +349 -0
- package/src/__tests__/predictive-prospective-memory.test.ts +416 -0
- package/src/__tests__/preference-guard-smoke.test.ts +211 -0
- package/src/__tests__/preference-matcher.test.ts +230 -0
- package/src/__tests__/preference-slots.test.ts +205 -0
- package/src/__tests__/prospective-memory.test.ts +283 -0
- package/src/__tests__/query-entity-detector.test.ts +171 -0
- package/src/__tests__/query-expander-alias.test.ts +146 -0
- package/src/__tests__/query-expander.test.ts +34 -0
- package/src/__tests__/recall-governor.test.ts +227 -0
- package/src/__tests__/recall-mode.test.ts +64 -0
- package/src/__tests__/result-synthesizer.test.ts +198 -0
- package/src/__tests__/resume-context.test.ts +4898 -0
- package/src/__tests__/retrieval-trace.test.ts +213 -0
- package/src/__tests__/retriever-boundary-weight.test.ts +136 -0
- package/src/__tests__/retroactive-boost.test.ts +223 -0
- package/src/__tests__/salience-scoring.test.ts +106 -0
- package/src/__tests__/scope-inventory.test.ts +200 -0
- package/src/__tests__/scope-policy.test.ts +69 -0
- package/src/__tests__/scope-suggester.test.ts +80 -0
- package/src/__tests__/session-checkpoint.test.ts +291 -0
- package/src/__tests__/session-distiller.test.ts +640 -0
- package/src/__tests__/session-gc.test.ts +215 -0
- package/src/__tests__/skill-engine.test.ts +552 -0
- package/src/__tests__/skill-promotion.test.ts +601 -0
- package/src/__tests__/skill-verifier.test.ts +122 -0
- package/src/__tests__/source-heartbeat.test.ts +250 -0
- package/src/__tests__/store-patch-metadata.test.ts +205 -0
- package/src/__tests__/store-scope-audit.test.ts +81 -0
- package/src/__tests__/store-upsert.test.ts +184 -0
- package/src/__tests__/supersede-chain.test.ts +154 -0
- package/src/__tests__/temporal-parser.test.ts +241 -0
- package/src/__tests__/temporal-validity.test.ts +160 -0
- package/src/__tests__/term-registry.test.ts +121 -0
- package/src/__tests__/tool-error-surfacing.test.ts +98 -0
- package/src/__tests__/tool-output-compressor.test.ts +160 -0
- package/src/__tests__/topic-tag.test.ts +113 -0
- package/src/__tests__/trusted-memory.test.ts +839 -0
- package/src/__tests__/usage-tracker.test.ts +287 -0
- package/src/__tests__/version-manager.test.ts +213 -0
- package/src/__tests__/workflow-observation-skill-outcome.test.ts +352 -0
- package/src/__tests__/workflow-observation.test.ts +433 -0
- package/src/__tests__/write-verifier.test.ts +122 -0
- package/src/access-tracker.ts +38 -32
- package/src/activity-counter.ts +46 -18
- package/src/aliases.ts +133 -0
- package/src/api-server.ts +27 -7
- package/src/audit-log.ts +4 -2
- package/src/auto-consolidation.ts +8 -3
- package/src/auto-gc.ts +85 -21
- package/src/capture-engine.ts +54 -21
- package/src/cli.ts +199 -37
- package/src/confidence-tracker.ts +36 -18
- package/src/connector-types.ts +57 -0
- package/src/consolidation-engine.ts +109 -11
- package/src/context-composer.ts +8 -1
- package/src/conversation-importer.ts +25 -1
- package/src/data-checkup.ts +126 -7
- package/src/distill-lock.ts +194 -15
- package/src/doctor.ts +38 -2
- package/src/dream-pipeline.ts +118 -34
- package/src/env-config.ts +77 -0
- package/src/error-signature.ts +153 -0
- package/src/error-taxonomy.ts +115 -0
- package/src/eval.ts +251 -6
- package/src/idempotency.ts +8 -0
- package/src/ingest.ts +234 -10
- package/src/kg-extractor.ts +6 -2
- package/src/kg-store.ts +236 -44
- package/src/llm-consolidation.ts +2 -1
- package/src/mcp-server.ts +85 -1799
- package/src/mcp-tool-deps.ts +48 -0
- package/src/mcp-tools-advanced.ts +941 -0
- package/src/mcp-tools-core.ts +633 -0
- package/src/mcp-tools-governance.ts +475 -0
- package/src/memory-boundaries.ts +3 -1
- package/src/memory-evolution.ts +73 -1
- package/src/memory-lint.ts +183 -10
- package/src/memory-output.ts +114 -3
- package/src/memory-promotion.ts +246 -0
- package/src/memory-schema.ts +25 -2
- package/src/memory-store-port.ts +43 -0
- package/src/multi-vector.ts +2 -1
- package/src/narrative-schema.ts +2 -1
- package/src/noise-filter.ts +57 -6
- package/src/obsidian-connector.ts +282 -0
- package/src/pii-detector.ts +157 -5
- package/src/query-expander.ts +90 -9
- package/src/result-synthesizer.ts +2 -1
- package/src/retention-policy.ts +2 -1
- package/src/retriever.ts +259 -139
- package/src/runtime-config.ts +8 -1
- package/src/scope-suggester.ts +113 -0
- package/src/session-distiller.ts +23 -2
- package/src/session-engine.ts +2 -1
- package/src/session-schema.ts +3 -2
- package/src/session-store.ts +5 -0
- package/src/skill-engine.ts +78 -0
- package/src/skill-promotion.ts +247 -47
- package/src/skill-schema.ts +16 -3
- package/src/skill-verifier.ts +152 -0
- package/src/source-heartbeat.ts +108 -0
- package/src/store.ts +267 -38
- package/src/tool-output-compressor.ts +3 -1
- package/src/ui-server.ts +2 -1
- package/src/usage-tracker.ts +242 -0
- package/src/version-manager.ts +3 -2
- package/src/workflow-observation-engine.ts +2 -1
- package/src/workflow-observation-schema.ts +2 -1
- package/src/workflow-observation-store.ts +6 -2
- package/.env +0 -4
- package/CLAUDE.md +0 -46
- package/config.json +0 -55
- package/daily-recall.sh +0 -110
- package/logs/daily-recall.error.log +0 -0
- package/logs/daily-recall.log +0 -30
- package/logs/ingest-2026-04-11.log +0 -110
- package/logs/ingest-2026-04-12.log +0 -90
- package/logs/launchagent-stderr.log +0 -0
- package/logs/launchagent-stdout.log +0 -0
package/config.json.example
CHANGED
|
@@ -28,11 +28,14 @@
|
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
"retrieval": {
|
|
31
|
-
"mode": "
|
|
31
|
+
"mode": "vector",
|
|
32
32
|
"vectorWeight": 0.7,
|
|
33
33
|
"bm25Weight": 0.3,
|
|
34
34
|
"recencyHalfLifeDays": 30,
|
|
35
35
|
"timeDecayHalfLifeDays": 120,
|
|
36
36
|
"hardMinScore": 0.3
|
|
37
|
+
},
|
|
38
|
+
"scopeRelations": {
|
|
39
|
+
"project:example-a": ["project:example-b"]
|
|
37
40
|
}
|
|
38
41
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Email Connector Adapter (skeleton)
|
|
4
|
+
*
|
|
5
|
+
* Demonstrates how to produce a ConnectorOutputV1 JSON file from an email
|
|
6
|
+
* source (IMAP, Gmail API, local mbox, etc.) for RecallNest ingestion.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* bun run connectors/examples/email-adapter.ts > email-output.json
|
|
10
|
+
* lm ingest --connector email-output.json
|
|
11
|
+
*
|
|
12
|
+
* Customize:
|
|
13
|
+
* 1. Replace the fetchEmails() stub with your IMAP/API client
|
|
14
|
+
* 2. Adjust scope to match your project naming
|
|
15
|
+
* 3. Set categoryHint based on email type (meeting invite → "events", etc.)
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { ConnectorOutputV1 } from "../../src/connector-types.js";
|
|
19
|
+
import { createHash } from "node:crypto";
|
|
20
|
+
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// TODO: Replace with real email fetching logic
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
interface RawEmail {
|
|
26
|
+
messageId: string;
|
|
27
|
+
subject: string;
|
|
28
|
+
body: string;
|
|
29
|
+
from: string;
|
|
30
|
+
date: string; // ISO 8601
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function fetchEmails(_since: Date): Promise<RawEmail[]> {
|
|
34
|
+
// Example: use imapflow, googleapis, or read from .mbox
|
|
35
|
+
// const client = new ImapFlow({ host: 'imap.example.com', ... });
|
|
36
|
+
// await client.connect();
|
|
37
|
+
// const messages = await client.fetch(...);
|
|
38
|
+
return []; // Replace with real implementation
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Transform → ConnectorOutputV1
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
async function main() {
|
|
46
|
+
const since = new Date(Date.now() - 7 * 86_400_000); // last 7 days
|
|
47
|
+
const emails = await fetchEmails(since);
|
|
48
|
+
|
|
49
|
+
const output: ConnectorOutputV1 = {
|
|
50
|
+
version: "connector-v1",
|
|
51
|
+
source: "email",
|
|
52
|
+
scope: "inbox:personal", // Customize: "inbox:work", "project:xyz"
|
|
53
|
+
producedAt: new Date().toISOString(),
|
|
54
|
+
records: emails.map((email) => ({
|
|
55
|
+
id: `email:${email.messageId}`,
|
|
56
|
+
text: email.body,
|
|
57
|
+
title: email.subject,
|
|
58
|
+
categoryHint: "events", // Customize per email type
|
|
59
|
+
importanceHint: 0.6, // Customize: 0.9 for flagged/starred
|
|
60
|
+
tags: ["email", `from:${email.from}`],
|
|
61
|
+
timestamp: email.date,
|
|
62
|
+
contentHash: createHash("sha256").update(email.body).digest("hex"),
|
|
63
|
+
sourceMetadata: {
|
|
64
|
+
from: email.from,
|
|
65
|
+
messageId: email.messageId,
|
|
66
|
+
},
|
|
67
|
+
})),
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
console.log(JSON.stringify(output, null, 2));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Log File Connector Adapter (skeleton)
|
|
4
|
+
*
|
|
5
|
+
* Demonstrates how to produce a ConnectorOutputV1 JSON file from application
|
|
6
|
+
* log files for RecallNest ingestion. Useful for tracking deploy events,
|
|
7
|
+
* error patterns, and operational decisions.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* bun run connectors/examples/logs-adapter.ts /var/log/myapp/*.log > logs-output.json
|
|
11
|
+
* lm ingest --connector logs-output.json
|
|
12
|
+
*
|
|
13
|
+
* Customize:
|
|
14
|
+
* 1. Replace parseLogLine() with your log format parser
|
|
15
|
+
* 2. Adjust the importance/category logic for your use case
|
|
16
|
+
* 3. Set scope to match your project
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type { ConnectorOutputV1 } from "../../src/connector-types.js";
|
|
20
|
+
import { readFileSync } from "node:fs";
|
|
21
|
+
import { createHash } from "node:crypto";
|
|
22
|
+
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// TODO: Replace with your log format parser
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
interface ParsedLogEntry {
|
|
28
|
+
timestamp: string; // ISO 8601
|
|
29
|
+
level: "info" | "warn" | "error" | "debug";
|
|
30
|
+
message: string;
|
|
31
|
+
source?: string; // e.g. module name, service
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function parseLogLine(line: string): ParsedLogEntry | null {
|
|
35
|
+
// Example: "2026-04-14T10:00:00Z [ERROR] auth: login failed for user@example.com"
|
|
36
|
+
const match = line.match(
|
|
37
|
+
/^(\d{4}-\d{2}-\d{2}T[\d:.]+Z?)\s+\[(\w+)]\s+(?:(\w+):\s+)?(.+)$/,
|
|
38
|
+
);
|
|
39
|
+
if (!match) return null;
|
|
40
|
+
return {
|
|
41
|
+
timestamp: match[1],
|
|
42
|
+
level: match[2].toLowerCase() as ParsedLogEntry["level"],
|
|
43
|
+
source: match[3],
|
|
44
|
+
message: match[4],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function levelToImportance(level: string): number {
|
|
49
|
+
switch (level) {
|
|
50
|
+
case "error": return 0.9;
|
|
51
|
+
case "warn": return 0.7;
|
|
52
|
+
case "info": return 0.5;
|
|
53
|
+
default: return 0.3;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// Transform → ConnectorOutputV1
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
|
|
61
|
+
function main() {
|
|
62
|
+
const files = process.argv.slice(2);
|
|
63
|
+
if (files.length === 0) {
|
|
64
|
+
console.error("Usage: logs-adapter.ts <logfile> [logfile...]");
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const records: ConnectorOutputV1["records"] = [];
|
|
69
|
+
|
|
70
|
+
for (const file of files) {
|
|
71
|
+
const lines = readFileSync(file, "utf-8").split("\n").filter(Boolean);
|
|
72
|
+
for (const line of lines) {
|
|
73
|
+
const entry = parseLogLine(line);
|
|
74
|
+
if (!entry) continue;
|
|
75
|
+
|
|
76
|
+
// Skip debug-level by default — too noisy for memory storage
|
|
77
|
+
if (entry.level === "debug") continue;
|
|
78
|
+
|
|
79
|
+
records.push({
|
|
80
|
+
id: `log:${createHash("md5").update(line).digest("hex")}`,
|
|
81
|
+
text: entry.message,
|
|
82
|
+
title: entry.source ? `[${entry.level.toUpperCase()}] ${entry.source}` : undefined,
|
|
83
|
+
categoryHint: entry.level === "error" ? "cases" : "events",
|
|
84
|
+
importanceHint: levelToImportance(entry.level),
|
|
85
|
+
tags: ["log", entry.level, ...(entry.source ? [`module:${entry.source}`] : [])],
|
|
86
|
+
timestamp: entry.timestamp,
|
|
87
|
+
contentHash: createHash("sha256").update(line).digest("hex"),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const output: ConnectorOutputV1 = {
|
|
93
|
+
version: "connector-v1",
|
|
94
|
+
source: "logs",
|
|
95
|
+
scope: "ops:myapp", // Customize: "project:xyz", "ops:production"
|
|
96
|
+
producedAt: new Date().toISOString(),
|
|
97
|
+
records,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
console.log(JSON.stringify(output, null, 2));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
main();
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* RSS Feed Connector Adapter (skeleton)
|
|
4
|
+
*
|
|
5
|
+
* Demonstrates how to produce a ConnectorOutputV1 JSON file from RSS/Atom
|
|
6
|
+
* feeds for RecallNest ingestion. Useful for tracking industry news,
|
|
7
|
+
* blog posts, and research updates.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* bun run connectors/examples/rss-adapter.ts > rss-output.json
|
|
11
|
+
* lm ingest --connector rss-output.json
|
|
12
|
+
*
|
|
13
|
+
* Customize:
|
|
14
|
+
* 1. Replace fetchFeed() with your RSS parsing library (e.g. rss-parser)
|
|
15
|
+
* 2. Adjust feed URLs and scope
|
|
16
|
+
* 3. Set categoryHint / importanceHint based on feed type
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type { ConnectorOutputV1 } from "../../src/connector-types.js";
|
|
20
|
+
import { createHash } from "node:crypto";
|
|
21
|
+
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// TODO: Replace with real RSS/Atom parsing
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
interface FeedItem {
|
|
27
|
+
guid: string;
|
|
28
|
+
title: string;
|
|
29
|
+
content: string; // HTML stripped to plain text
|
|
30
|
+
link: string;
|
|
31
|
+
pubDate: string; // ISO 8601
|
|
32
|
+
categories?: string[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface FeedConfig {
|
|
36
|
+
url: string;
|
|
37
|
+
scope: string; // e.g. "feeds:ai-news"
|
|
38
|
+
categoryHint?: string;
|
|
39
|
+
importanceHint?: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const FEEDS: FeedConfig[] = [
|
|
43
|
+
// Add your feeds here:
|
|
44
|
+
// { url: "https://example.com/feed.xml", scope: "feeds:example" },
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
async function fetchFeed(_url: string): Promise<FeedItem[]> {
|
|
48
|
+
// Example with rss-parser:
|
|
49
|
+
// import Parser from "rss-parser";
|
|
50
|
+
// const parser = new Parser();
|
|
51
|
+
// const feed = await parser.parseURL(url);
|
|
52
|
+
// return feed.items.map(item => ({ ... }));
|
|
53
|
+
return []; // Replace with real implementation
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Transform → ConnectorOutputV1
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
async function main() {
|
|
61
|
+
for (const feed of FEEDS) {
|
|
62
|
+
const items = await fetchFeed(feed.url);
|
|
63
|
+
|
|
64
|
+
const output: ConnectorOutputV1 = {
|
|
65
|
+
version: "connector-v1",
|
|
66
|
+
source: "rss",
|
|
67
|
+
scope: feed.scope,
|
|
68
|
+
producedAt: new Date().toISOString(),
|
|
69
|
+
records: items.map((item) => ({
|
|
70
|
+
id: `rss:${createHash("md5").update(item.guid || item.link).digest("hex")}`,
|
|
71
|
+
text: item.content,
|
|
72
|
+
title: item.title,
|
|
73
|
+
categoryHint: feed.categoryHint ?? "knowledge",
|
|
74
|
+
importanceHint: feed.importanceHint ?? 0.6,
|
|
75
|
+
tags: [
|
|
76
|
+
"rss",
|
|
77
|
+
...(item.categories ?? []),
|
|
78
|
+
`link:${item.link}`,
|
|
79
|
+
],
|
|
80
|
+
timestamp: item.pubDate,
|
|
81
|
+
contentHash: createHash("sha256").update(item.content).digest("hex"),
|
|
82
|
+
sourceMetadata: {
|
|
83
|
+
feedUrl: feed.url,
|
|
84
|
+
link: item.link,
|
|
85
|
+
guid: item.guid,
|
|
86
|
+
},
|
|
87
|
+
})),
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// Each feed outputs one JSON — pipe to separate files if needed
|
|
91
|
+
console.log(JSON.stringify(output, null, 2));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
main().catch(console.error);
|