nodebench-mcp 2.69.0 → 3.0.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/README.md +95 -39
- package/dist/agents/alertRouter.d.ts +38 -0
- package/dist/agents/alertRouter.js +151 -0
- package/dist/agents/alertRouter.js.map +1 -0
- package/dist/agents/entityMemory.d.ts +40 -0
- package/dist/agents/entityMemory.js +64 -0
- package/dist/agents/entityMemory.js.map +1 -0
- package/dist/agents/subAgents.d.ts +35 -0
- package/dist/agents/subAgents.js +62 -0
- package/dist/agents/subAgents.js.map +1 -0
- package/dist/benchmarks/benchmarkRunner.js +14 -0
- package/dist/benchmarks/benchmarkRunner.js.map +1 -1
- package/dist/benchmarks/chainEval.js +107 -0
- package/dist/benchmarks/chainEval.js.map +1 -1
- package/dist/benchmarks/llmJudgeEval.js +85 -0
- package/dist/benchmarks/llmJudgeEval.js.map +1 -1
- package/dist/benchmarks/searchQualityEval.js +118 -5
- package/dist/benchmarks/searchQualityEval.js.map +1 -1
- package/dist/cli/search.d.ts +13 -0
- package/dist/cli/search.js +130 -0
- package/dist/cli/search.js.map +1 -0
- package/dist/db.d.ts +6 -2
- package/dist/db.js +470 -3
- package/dist/db.js.map +1 -1
- package/dist/index.js +349 -64
- package/dist/index.js.map +1 -1
- package/dist/profiler/behaviorStore.d.ts +97 -0
- package/dist/profiler/behaviorStore.js +276 -0
- package/dist/profiler/behaviorStore.js.map +1 -0
- package/dist/profiler/eventCollector.d.ts +119 -0
- package/dist/profiler/eventCollector.js +267 -0
- package/dist/profiler/eventCollector.js.map +1 -0
- package/dist/profiler/index.d.ts +15 -0
- package/dist/profiler/index.js +16 -0
- package/dist/profiler/index.js.map +1 -0
- package/dist/profiler/mcpProxy.d.ts +49 -0
- package/dist/profiler/mcpProxy.js +123 -0
- package/dist/profiler/mcpProxy.js.map +1 -0
- package/dist/profiler/modelRouter.d.ts +30 -0
- package/dist/profiler/modelRouter.js +99 -0
- package/dist/profiler/modelRouter.js.map +1 -0
- package/dist/profiler/otelReceiver.d.ts +17 -0
- package/dist/profiler/otelReceiver.js +62 -0
- package/dist/profiler/otelReceiver.js.map +1 -0
- package/dist/profiler/proofEngine.d.ts +41 -0
- package/dist/profiler/proofEngine.js +93 -0
- package/dist/profiler/proofEngine.js.map +1 -0
- package/dist/profiler/workflowTemplates.d.ts +41 -0
- package/dist/profiler/workflowTemplates.js +95 -0
- package/dist/profiler/workflowTemplates.js.map +1 -0
- package/dist/providers/localMemoryProvider.js +3 -2
- package/dist/providers/localMemoryProvider.js.map +1 -1
- package/dist/runtimeConfig.d.ts +11 -0
- package/dist/runtimeConfig.js +27 -0
- package/dist/runtimeConfig.js.map +1 -0
- package/dist/security/auditLog.js +8 -3
- package/dist/security/auditLog.js.map +1 -1
- package/dist/subconscious/blocks.d.ts +43 -0
- package/dist/subconscious/blocks.js +158 -0
- package/dist/subconscious/blocks.js.map +1 -0
- package/dist/subconscious/classifier.d.ts +22 -0
- package/dist/subconscious/classifier.js +118 -0
- package/dist/subconscious/classifier.js.map +1 -0
- package/dist/subconscious/graphEngine.d.ts +65 -0
- package/dist/subconscious/graphEngine.js +234 -0
- package/dist/subconscious/graphEngine.js.map +1 -0
- package/dist/subconscious/index.d.ts +19 -0
- package/dist/subconscious/index.js +20 -0
- package/dist/subconscious/index.js.map +1 -0
- package/dist/subconscious/tools.d.ts +5 -0
- package/dist/subconscious/tools.js +255 -0
- package/dist/subconscious/tools.js.map +1 -0
- package/dist/subconscious/whisperPolicy.d.ts +20 -0
- package/dist/subconscious/whisperPolicy.js +171 -0
- package/dist/subconscious/whisperPolicy.js.map +1 -0
- package/dist/sweep/engine.d.ts +27 -0
- package/dist/sweep/engine.js +244 -0
- package/dist/sweep/engine.js.map +1 -0
- package/dist/sweep/index.d.ts +9 -0
- package/dist/sweep/index.js +8 -0
- package/dist/sweep/index.js.map +1 -0
- package/dist/sweep/sources/github_trending.d.ts +6 -0
- package/dist/sweep/sources/github_trending.js +37 -0
- package/dist/sweep/sources/github_trending.js.map +1 -0
- package/dist/sweep/sources/hackernews.d.ts +7 -0
- package/dist/sweep/sources/hackernews.js +57 -0
- package/dist/sweep/sources/hackernews.js.map +1 -0
- package/dist/sweep/sources/openbb_finance.d.ts +9 -0
- package/dist/sweep/sources/openbb_finance.js +46 -0
- package/dist/sweep/sources/openbb_finance.js.map +1 -0
- package/dist/sweep/sources/producthunt.d.ts +6 -0
- package/dist/sweep/sources/producthunt.js +41 -0
- package/dist/sweep/sources/producthunt.js.map +1 -0
- package/dist/sweep/sources/web_signals.d.ts +7 -0
- package/dist/sweep/sources/web_signals.js +63 -0
- package/dist/sweep/sources/web_signals.js.map +1 -0
- package/dist/sweep/sources/yahoo_finance.d.ts +6 -0
- package/dist/sweep/sources/yahoo_finance.js +47 -0
- package/dist/sweep/sources/yahoo_finance.js.map +1 -0
- package/dist/sweep/types.d.ts +50 -0
- package/dist/sweep/types.js +9 -0
- package/dist/sweep/types.js.map +1 -0
- package/dist/sync/founderEpisodeStore.d.ts +98 -0
- package/dist/sync/founderEpisodeStore.js +230 -0
- package/dist/sync/founderEpisodeStore.js.map +1 -0
- package/dist/sync/hyperloopArchive.d.ts +51 -0
- package/dist/sync/hyperloopArchive.js +153 -0
- package/dist/sync/hyperloopArchive.js.map +1 -0
- package/dist/sync/hyperloopEval.d.ts +123 -0
- package/dist/sync/hyperloopEval.js +389 -0
- package/dist/sync/hyperloopEval.js.map +1 -0
- package/dist/sync/hyperloopEval.test.d.ts +4 -0
- package/dist/sync/hyperloopEval.test.js +60 -0
- package/dist/sync/hyperloopEval.test.js.map +1 -0
- package/dist/sync/protocol.d.ts +172 -0
- package/dist/sync/protocol.js +9 -0
- package/dist/sync/protocol.js.map +1 -0
- package/dist/sync/sessionMemory.d.ts +47 -0
- package/dist/sync/sessionMemory.js +138 -0
- package/dist/sync/sessionMemory.js.map +1 -0
- package/dist/sync/store.d.ts +384 -0
- package/dist/sync/store.js +1435 -0
- package/dist/sync/store.js.map +1 -0
- package/dist/sync/store.test.d.ts +4 -0
- package/dist/sync/store.test.js +43 -0
- package/dist/sync/store.test.js.map +1 -0
- package/dist/sync/syncBridgeClient.d.ts +30 -0
- package/dist/sync/syncBridgeClient.js +172 -0
- package/dist/sync/syncBridgeClient.js.map +1 -0
- package/dist/tools/autonomousDeliveryTools.d.ts +2 -0
- package/dist/tools/autonomousDeliveryTools.js +1104 -0
- package/dist/tools/autonomousDeliveryTools.js.map +1 -0
- package/dist/tools/claudeCodeIngestTools.d.ts +10 -0
- package/dist/tools/claudeCodeIngestTools.js +347 -0
- package/dist/tools/claudeCodeIngestTools.js.map +1 -0
- package/dist/tools/coreWorkflowTools.d.ts +2 -0
- package/dist/tools/coreWorkflowTools.js +488 -0
- package/dist/tools/coreWorkflowTools.js.map +1 -0
- package/dist/tools/deltaTools.d.ts +15 -0
- package/dist/tools/deltaTools.js +1522 -0
- package/dist/tools/deltaTools.js.map +1 -0
- package/dist/tools/entityLookupTools.d.ts +14 -0
- package/dist/tools/entityLookupTools.js +159 -0
- package/dist/tools/entityLookupTools.js.map +1 -0
- package/dist/tools/entityTemporalTools.d.ts +12 -0
- package/dist/tools/entityTemporalTools.js +330 -0
- package/dist/tools/entityTemporalTools.js.map +1 -0
- package/dist/tools/founderLocalPipeline.d.ts +215 -0
- package/dist/tools/founderLocalPipeline.js +1516 -2
- package/dist/tools/founderLocalPipeline.js.map +1 -1
- package/dist/tools/founderOperatingModel.d.ts +120 -0
- package/dist/tools/founderOperatingModel.js +469 -0
- package/dist/tools/founderOperatingModel.js.map +1 -0
- package/dist/tools/founderOperatingModelTools.d.ts +2 -0
- package/dist/tools/founderOperatingModelTools.js +169 -0
- package/dist/tools/founderOperatingModelTools.js.map +1 -0
- package/dist/tools/founderStrategicOpsTools.d.ts +2 -0
- package/dist/tools/founderStrategicOpsTools.js +1310 -0
- package/dist/tools/founderStrategicOpsTools.js.map +1 -0
- package/dist/tools/graphifyTools.d.ts +19 -0
- package/dist/tools/graphifyTools.js +375 -0
- package/dist/tools/graphifyTools.js.map +1 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.js +4 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/monteCarloTools.d.ts +16 -0
- package/dist/tools/monteCarloTools.js +225 -0
- package/dist/tools/monteCarloTools.js.map +1 -0
- package/dist/tools/packetCompilerTools.d.ts +12 -0
- package/dist/tools/packetCompilerTools.js +322 -0
- package/dist/tools/packetCompilerTools.js.map +1 -0
- package/dist/tools/planSynthesisTools.d.ts +15 -0
- package/dist/tools/planSynthesisTools.js +455 -0
- package/dist/tools/planSynthesisTools.js.map +1 -0
- package/dist/tools/profilerTools.d.ts +20 -0
- package/dist/tools/profilerTools.js +364 -0
- package/dist/tools/profilerTools.js.map +1 -0
- package/dist/tools/savingsTools.d.ts +11 -0
- package/dist/tools/savingsTools.js +155 -0
- package/dist/tools/savingsTools.js.map +1 -0
- package/dist/tools/scenarioCompilerTools.d.ts +14 -0
- package/dist/tools/scenarioCompilerTools.js +290 -0
- package/dist/tools/scenarioCompilerTools.js.map +1 -0
- package/dist/tools/sharedContextTools.d.ts +2 -0
- package/dist/tools/sharedContextTools.js +423 -0
- package/dist/tools/sharedContextTools.js.map +1 -0
- package/dist/tools/sitemapTools.d.ts +15 -0
- package/dist/tools/sitemapTools.js +560 -0
- package/dist/tools/sitemapTools.js.map +1 -0
- package/dist/tools/sweepTools.d.ts +9 -0
- package/dist/tools/sweepTools.js +112 -0
- package/dist/tools/sweepTools.js.map +1 -0
- package/dist/tools/syncBridgeTools.d.ts +2 -0
- package/dist/tools/syncBridgeTools.js +258 -0
- package/dist/tools/syncBridgeTools.js.map +1 -0
- package/dist/tools/toolRegistry.js +1216 -49
- package/dist/tools/toolRegistry.js.map +1 -1
- package/dist/tools/workspaceTools.d.ts +19 -0
- package/dist/tools/workspaceTools.js +762 -0
- package/dist/tools/workspaceTools.js.map +1 -0
- package/dist/toolsetRegistry.js +88 -2
- package/dist/toolsetRegistry.js.map +1 -1
- package/package.json +36 -36
- package/rules/nodebench-agentic-reliability.md +32 -0
- package/rules/nodebench-analyst-diagnostic.md +25 -0
- package/rules/nodebench-auto-qa.md +31 -0
- package/rules/nodebench-completion-traceability.md +22 -0
- package/rules/nodebench-flywheel-continuous.md +25 -0
- package/rules/nodebench-pre-release-review.md +24 -0
- package/rules/nodebench-qa-dogfood.md +26 -0
- package/rules/nodebench-scenario-testing.md +30 -0
- package/rules/nodebench-self-direction.md +23 -0
- package/rules/nodebench-self-judge-loop.md +24 -0
- package/scripts/install.sh +215 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whisper Policy — decides what to inject and what to suppress.
|
|
3
|
+
*
|
|
4
|
+
* Suppression-first: default is NO whisper unless high-value signal.
|
|
5
|
+
* Classification-driven: prompt type determines which blocks to inject.
|
|
6
|
+
*/
|
|
7
|
+
import { getBlocksByIds, getBlock, getStaleBlocks, logWhisper, getRecentWhispers } from "./blocks.js";
|
|
8
|
+
import { classifyPrompt, isTrivialPrompt } from "./classifier.js";
|
|
9
|
+
import { findContradictions, resolveEntity } from "./graphEngine.js";
|
|
10
|
+
// ── Token Budgets ──────────────────────────────────────────────────────────
|
|
11
|
+
const TOKEN_BUDGETS = {
|
|
12
|
+
off: 0,
|
|
13
|
+
whisper: 200,
|
|
14
|
+
packet: 1000,
|
|
15
|
+
full: 2000,
|
|
16
|
+
review: 0,
|
|
17
|
+
};
|
|
18
|
+
// ── Main Whisper Generator ─────────────────────────────────────────────────
|
|
19
|
+
export function generateWhisper(prompt, sessionId, mode = "whisper") {
|
|
20
|
+
const classification = classifyPrompt(prompt);
|
|
21
|
+
// Mode: off or review → no injection
|
|
22
|
+
if (mode === "off" || mode === "review") {
|
|
23
|
+
return {
|
|
24
|
+
mode,
|
|
25
|
+
classification,
|
|
26
|
+
whisperText: "",
|
|
27
|
+
suppressed: true,
|
|
28
|
+
suppressionReason: `mode=${mode}`,
|
|
29
|
+
blockIdsUsed: [],
|
|
30
|
+
contradictions: [],
|
|
31
|
+
stalePackets: [],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// Suppression check: trivial prompts
|
|
35
|
+
if (isTrivialPrompt(prompt)) {
|
|
36
|
+
const result = {
|
|
37
|
+
mode,
|
|
38
|
+
classification,
|
|
39
|
+
whisperText: "",
|
|
40
|
+
suppressed: true,
|
|
41
|
+
suppressionReason: "trivial_prompt",
|
|
42
|
+
blockIdsUsed: [],
|
|
43
|
+
contradictions: [],
|
|
44
|
+
stalePackets: [],
|
|
45
|
+
};
|
|
46
|
+
logWhisper({
|
|
47
|
+
sessionId,
|
|
48
|
+
blockIds: [],
|
|
49
|
+
whisperText: "",
|
|
50
|
+
classification: classification.classification,
|
|
51
|
+
suppressed: true,
|
|
52
|
+
reason: "trivial_prompt",
|
|
53
|
+
});
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
// Suppression check: duplicate whisper (same classification <3 prompts ago)
|
|
57
|
+
const recentWhispers = getRecentWhispers(sessionId, 3);
|
|
58
|
+
const recentSameClass = recentWhispers.filter((w) => !w.suppressed && w.classification === classification.classification);
|
|
59
|
+
if (recentSameClass.length >= 2) {
|
|
60
|
+
const result = {
|
|
61
|
+
mode,
|
|
62
|
+
classification,
|
|
63
|
+
whisperText: "",
|
|
64
|
+
suppressed: true,
|
|
65
|
+
suppressionReason: "duplicate_recent",
|
|
66
|
+
blockIdsUsed: [],
|
|
67
|
+
contradictions: [],
|
|
68
|
+
stalePackets: [],
|
|
69
|
+
};
|
|
70
|
+
logWhisper({
|
|
71
|
+
sessionId,
|
|
72
|
+
blockIds: [],
|
|
73
|
+
whisperText: "",
|
|
74
|
+
classification: classification.classification,
|
|
75
|
+
suppressed: true,
|
|
76
|
+
reason: "duplicate_recent",
|
|
77
|
+
});
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
// Build whisper content
|
|
81
|
+
const blocks = getBlocksByIds(classification.relevantBlocks);
|
|
82
|
+
const populatedBlocks = blocks.filter((b) => b.value.length > 0);
|
|
83
|
+
const lines = [];
|
|
84
|
+
const blockIdsUsed = [];
|
|
85
|
+
// Check for contradictions via graph traversal
|
|
86
|
+
const contradictions = [];
|
|
87
|
+
for (const entityName of classification.entities) {
|
|
88
|
+
const entity = resolveEntity(entityName);
|
|
89
|
+
if (!entity)
|
|
90
|
+
continue;
|
|
91
|
+
const contradictionResults = findContradictions(entity.id, 2);
|
|
92
|
+
for (const cr of contradictionResults.slice(0, 2)) {
|
|
93
|
+
contradictions.push(`"${entity.label}" contradicts "${cr.entity.label}" (via ${cr.reachedVia}, confidence ${(cr.confidence * 100).toFixed(0)}%)`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Check for stale packets
|
|
97
|
+
const stalePackets = [];
|
|
98
|
+
const packetLineage = getBlock("packet_lineage");
|
|
99
|
+
if (packetLineage.value.length > 0) {
|
|
100
|
+
const staleBlocks = getStaleBlocks(7);
|
|
101
|
+
for (const sb of staleBlocks.slice(0, 3)) {
|
|
102
|
+
stalePackets.push(`${sb.label} (last updated: ${sb.updatedAt.split("T")[0]})`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Build whisper text based on mode
|
|
106
|
+
if (mode === "whisper") {
|
|
107
|
+
// 1-3 lines max
|
|
108
|
+
if (contradictions.length > 0) {
|
|
109
|
+
lines.push(`Contradiction: ${contradictions[0]}`);
|
|
110
|
+
}
|
|
111
|
+
if (populatedBlocks.length > 0) {
|
|
112
|
+
const topBlock = populatedBlocks[0];
|
|
113
|
+
const firstLine = topBlock.value.split("\n")[0].slice(0, 100);
|
|
114
|
+
lines.push(`${topBlock.label}: ${firstLine}`);
|
|
115
|
+
blockIdsUsed.push(topBlock.id);
|
|
116
|
+
}
|
|
117
|
+
if (stalePackets.length > 0) {
|
|
118
|
+
lines.push(`Stale: ${stalePackets[0]}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else if (mode === "packet" || mode === "full") {
|
|
122
|
+
// Richer injection
|
|
123
|
+
if (contradictions.length > 0) {
|
|
124
|
+
lines.push("Contradictions:");
|
|
125
|
+
for (const c of contradictions)
|
|
126
|
+
lines.push(` - ${c}`);
|
|
127
|
+
}
|
|
128
|
+
for (const block of populatedBlocks) {
|
|
129
|
+
const budget = mode === "full" ? 500 : 200;
|
|
130
|
+
const truncated = block.value.slice(0, budget);
|
|
131
|
+
lines.push(`\n[${block.label}] (v${block.version}, ${block.confidence})`);
|
|
132
|
+
lines.push(truncated);
|
|
133
|
+
blockIdsUsed.push(block.id);
|
|
134
|
+
}
|
|
135
|
+
if (stalePackets.length > 0) {
|
|
136
|
+
lines.push("\nStale blocks:");
|
|
137
|
+
for (const sp of stalePackets)
|
|
138
|
+
lines.push(` - ${sp}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Truncate to token budget (rough: 4 chars per token)
|
|
142
|
+
const budget = TOKEN_BUDGETS[mode];
|
|
143
|
+
let whisperText = lines.join("\n");
|
|
144
|
+
if (whisperText.length > budget * 4) {
|
|
145
|
+
whisperText = whisperText.slice(0, budget * 4) + "\n...";
|
|
146
|
+
}
|
|
147
|
+
// Wrap in XML tag for Claude Code injection
|
|
148
|
+
if (whisperText.length > 0) {
|
|
149
|
+
whisperText = `<nodebench_whisper>\n${whisperText}\n</nodebench_whisper>`;
|
|
150
|
+
}
|
|
151
|
+
// Log
|
|
152
|
+
logWhisper({
|
|
153
|
+
sessionId,
|
|
154
|
+
blockIds: blockIdsUsed,
|
|
155
|
+
whisperText,
|
|
156
|
+
classification: classification.classification,
|
|
157
|
+
suppressed: false,
|
|
158
|
+
reason: null,
|
|
159
|
+
});
|
|
160
|
+
return {
|
|
161
|
+
mode,
|
|
162
|
+
classification,
|
|
163
|
+
whisperText,
|
|
164
|
+
suppressed: whisperText.length === 0,
|
|
165
|
+
suppressionReason: whisperText.length === 0 ? "no_relevant_blocks" : null,
|
|
166
|
+
blockIdsUsed,
|
|
167
|
+
contradictions,
|
|
168
|
+
stalePackets,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=whisperPolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whisperPolicy.js","sourceRoot":"","sources":["../../src/subconscious/whisperPolicy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sweep Engine — runs all data source collectors in parallel,
|
|
3
|
+
* computes deltas, and produces the top signal for auto-fire.
|
|
4
|
+
*
|
|
5
|
+
* Pattern: Crucix's briefing.mjs master orchestrator
|
|
6
|
+
* Architecture: DeerFlow's sub-agent parallel dispatch
|
|
7
|
+
*
|
|
8
|
+
* Each source is a self-contained module that exports collect().
|
|
9
|
+
* The engine runs them all with timeouts, collects signals,
|
|
10
|
+
* computes what changed since last sweep, and identifies the
|
|
11
|
+
* top entity for the landing page.
|
|
12
|
+
*/
|
|
13
|
+
import type { SweepSignal, SweepResult, DeltaResult, SourceCollector } from "./types.js";
|
|
14
|
+
export declare function registerSource(name: string, collect: SourceCollector): void;
|
|
15
|
+
export declare function runSweep(): Promise<SweepResult>;
|
|
16
|
+
export declare function computeDelta(current: SweepResult, previous: SweepResult | null): DeltaResult;
|
|
17
|
+
export declare function initSweepTables(): void;
|
|
18
|
+
export declare function getLatestSweep(): SweepResult | null;
|
|
19
|
+
export declare function getPreviousSweep(): SweepResult | null;
|
|
20
|
+
export interface Recommendation {
|
|
21
|
+
signal: SweepSignal;
|
|
22
|
+
action: string;
|
|
23
|
+
reasoning: string;
|
|
24
|
+
urgency: "act_now" | "this_week" | "monitor";
|
|
25
|
+
category: "competitive" | "opportunity" | "risk" | "market";
|
|
26
|
+
}
|
|
27
|
+
export declare function generateRecommendations(signals: SweepSignal[]): Recommendation[];
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sweep Engine — runs all data source collectors in parallel,
|
|
3
|
+
* computes deltas, and produces the top signal for auto-fire.
|
|
4
|
+
*
|
|
5
|
+
* Pattern: Crucix's briefing.mjs master orchestrator
|
|
6
|
+
* Architecture: DeerFlow's sub-agent parallel dispatch
|
|
7
|
+
*
|
|
8
|
+
* Each source is a self-contained module that exports collect().
|
|
9
|
+
* The engine runs them all with timeouts, collects signals,
|
|
10
|
+
* computes what changed since last sweep, and identifies the
|
|
11
|
+
* top entity for the landing page.
|
|
12
|
+
*/
|
|
13
|
+
import { getDb, genId } from "../db.js";
|
|
14
|
+
const SOURCE_MODULES = [];
|
|
15
|
+
export function registerSource(name, collect) {
|
|
16
|
+
SOURCE_MODULES.push({ name, collect });
|
|
17
|
+
}
|
|
18
|
+
// ── Sweep execution ──────────────────────────────────────────────────
|
|
19
|
+
export async function runSweep() {
|
|
20
|
+
const sweepId = genId("sweep");
|
|
21
|
+
const startMs = Date.now();
|
|
22
|
+
const sourceResults = [];
|
|
23
|
+
const allSignals = [];
|
|
24
|
+
// Load sources dynamically (lazy import to avoid bundling issues)
|
|
25
|
+
if (SOURCE_MODULES.length === 0) {
|
|
26
|
+
try {
|
|
27
|
+
const hn = await import("./sources/hackernews.js");
|
|
28
|
+
registerSource("hackernews", hn.collect);
|
|
29
|
+
}
|
|
30
|
+
catch { /* source unavailable */ }
|
|
31
|
+
try {
|
|
32
|
+
const gh = await import("./sources/github_trending.js");
|
|
33
|
+
registerSource("github_trending", gh.collect);
|
|
34
|
+
}
|
|
35
|
+
catch { /* source unavailable */ }
|
|
36
|
+
try {
|
|
37
|
+
const yf = await import("./sources/yahoo_finance.js");
|
|
38
|
+
registerSource("yahoo_finance", yf.collect);
|
|
39
|
+
}
|
|
40
|
+
catch { /* source unavailable */ }
|
|
41
|
+
try {
|
|
42
|
+
const ph = await import("./sources/producthunt.js");
|
|
43
|
+
registerSource("producthunt", ph.collect);
|
|
44
|
+
}
|
|
45
|
+
catch { /* source unavailable */ }
|
|
46
|
+
try {
|
|
47
|
+
const ob = await import("./sources/openbb_finance.js");
|
|
48
|
+
registerSource("openbb_finance", ob.collect);
|
|
49
|
+
}
|
|
50
|
+
catch { /* source unavailable */ }
|
|
51
|
+
}
|
|
52
|
+
// Run all sources in parallel with per-source timeouts (Crucix pattern)
|
|
53
|
+
const results = await Promise.all(SOURCE_MODULES.map(async (source) => {
|
|
54
|
+
const sourceStart = Date.now();
|
|
55
|
+
try {
|
|
56
|
+
const signals = await Promise.race([
|
|
57
|
+
source.collect(),
|
|
58
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 10000)),
|
|
59
|
+
]);
|
|
60
|
+
return {
|
|
61
|
+
name: source.name,
|
|
62
|
+
status: "ok",
|
|
63
|
+
count: signals.length,
|
|
64
|
+
durationMs: Date.now() - sourceStart,
|
|
65
|
+
signals,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return {
|
|
70
|
+
name: source.name,
|
|
71
|
+
status: "error",
|
|
72
|
+
count: 0,
|
|
73
|
+
durationMs: Date.now() - sourceStart,
|
|
74
|
+
signals: [],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}));
|
|
78
|
+
for (const r of results) {
|
|
79
|
+
sourceResults.push({ name: r.name, status: r.status, count: r.count, durationMs: r.durationMs });
|
|
80
|
+
allSignals.push(...r.signals);
|
|
81
|
+
}
|
|
82
|
+
// Sort by score descending
|
|
83
|
+
allSignals.sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
|
|
84
|
+
const result = {
|
|
85
|
+
signals: allSignals,
|
|
86
|
+
sources: sourceResults,
|
|
87
|
+
totalDurationMs: Date.now() - startMs,
|
|
88
|
+
sweepId,
|
|
89
|
+
timestamp: new Date().toISOString(),
|
|
90
|
+
};
|
|
91
|
+
// Persist sweep result
|
|
92
|
+
persistSweep(result);
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
// ── Delta engine (Crucix delta/engine.mjs pattern) ───────────────────
|
|
96
|
+
export function computeDelta(current, previous) {
|
|
97
|
+
const prevIds = new Set((previous?.signals ?? []).map(s => s.id));
|
|
98
|
+
const prevSeverities = new Map((previous?.signals ?? []).map(s => [s.id, s.severity]));
|
|
99
|
+
const newSignals = current.signals.filter(s => !prevIds.has(s.id));
|
|
100
|
+
const escalations = [];
|
|
101
|
+
const deescalations = [];
|
|
102
|
+
for (const sig of current.signals) {
|
|
103
|
+
const prevSev = prevSeverities.get(sig.id);
|
|
104
|
+
if (!prevSev)
|
|
105
|
+
continue;
|
|
106
|
+
const sevOrder = { flash: 3, priority: 2, routine: 1 };
|
|
107
|
+
if (sevOrder[sig.severity] > sevOrder[prevSev]) {
|
|
108
|
+
escalations.push({ signal: sig, from: prevSev, to: sig.severity });
|
|
109
|
+
}
|
|
110
|
+
else if (sevOrder[sig.severity] < sevOrder[prevSev]) {
|
|
111
|
+
deescalations.push({ signal: sig, from: prevSev, to: sig.severity });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Top entity = highest-scored new signal, or highest-scored escalation
|
|
115
|
+
const topCandidates = [
|
|
116
|
+
...newSignals.filter(s => s.severity === "flash"),
|
|
117
|
+
...escalations.map(e => e.signal),
|
|
118
|
+
...newSignals.filter(s => s.severity === "priority"),
|
|
119
|
+
...newSignals,
|
|
120
|
+
];
|
|
121
|
+
const topSignal = topCandidates[0] ?? current.signals[0] ?? null;
|
|
122
|
+
return {
|
|
123
|
+
newSignals,
|
|
124
|
+
escalations,
|
|
125
|
+
deescalations,
|
|
126
|
+
topEntity: topSignal?.entity ?? null,
|
|
127
|
+
topEntityQuery: topSignal
|
|
128
|
+
? `${topSignal.headline} — what does this mean for founders?`
|
|
129
|
+
: null,
|
|
130
|
+
topEntitySeverity: topSignal?.severity ?? null,
|
|
131
|
+
sweepId: current.sweepId,
|
|
132
|
+
previousSweepId: previous?.sweepId ?? null,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// ── Persistence ──────────────────────────────────────────────────────
|
|
136
|
+
export function initSweepTables() {
|
|
137
|
+
const db = getDb();
|
|
138
|
+
db.exec(`
|
|
139
|
+
CREATE TABLE IF NOT EXISTS sweep_results (
|
|
140
|
+
id TEXT PRIMARY KEY,
|
|
141
|
+
signals TEXT NOT NULL DEFAULT '[]',
|
|
142
|
+
sources TEXT NOT NULL DEFAULT '[]',
|
|
143
|
+
total_duration_ms INTEGER DEFAULT 0,
|
|
144
|
+
signal_count INTEGER DEFAULT 0,
|
|
145
|
+
top_entity TEXT,
|
|
146
|
+
top_entity_query TEXT,
|
|
147
|
+
new_signal_count INTEGER DEFAULT 0,
|
|
148
|
+
escalation_count INTEGER DEFAULT 0,
|
|
149
|
+
timestamp TEXT NOT NULL
|
|
150
|
+
);
|
|
151
|
+
CREATE INDEX IF NOT EXISTS idx_sr_ts ON sweep_results(timestamp);
|
|
152
|
+
`);
|
|
153
|
+
}
|
|
154
|
+
function persistSweep(result) {
|
|
155
|
+
try {
|
|
156
|
+
const db = getDb();
|
|
157
|
+
db.prepare(`
|
|
158
|
+
INSERT OR REPLACE INTO sweep_results (id, signals, sources, total_duration_ms, signal_count, timestamp)
|
|
159
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
160
|
+
`).run(result.sweepId, JSON.stringify(result.signals.slice(0, 50)), JSON.stringify(result.sources), result.totalDurationMs, result.signals.length, result.timestamp);
|
|
161
|
+
}
|
|
162
|
+
catch { /* persistence is non-blocking */ }
|
|
163
|
+
}
|
|
164
|
+
export function getLatestSweep() {
|
|
165
|
+
try {
|
|
166
|
+
const db = getDb();
|
|
167
|
+
const row = db.prepare(`SELECT * FROM sweep_results ORDER BY timestamp DESC LIMIT 1`).get();
|
|
168
|
+
if (!row)
|
|
169
|
+
return null;
|
|
170
|
+
return {
|
|
171
|
+
signals: JSON.parse(row.signals ?? "[]"),
|
|
172
|
+
sources: JSON.parse(row.sources ?? "[]"),
|
|
173
|
+
totalDurationMs: row.total_duration_ms,
|
|
174
|
+
sweepId: row.id,
|
|
175
|
+
timestamp: row.timestamp,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
export function getPreviousSweep() {
|
|
183
|
+
try {
|
|
184
|
+
const db = getDb();
|
|
185
|
+
const row = db.prepare(`SELECT * FROM sweep_results ORDER BY timestamp DESC LIMIT 1 OFFSET 1`).get();
|
|
186
|
+
if (!row)
|
|
187
|
+
return null;
|
|
188
|
+
return {
|
|
189
|
+
signals: JSON.parse(row.signals ?? "[]"),
|
|
190
|
+
sources: JSON.parse(row.sources ?? "[]"),
|
|
191
|
+
totalDurationMs: row.total_duration_ms,
|
|
192
|
+
sweepId: row.id,
|
|
193
|
+
timestamp: row.timestamp,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
export function generateRecommendations(signals) {
|
|
201
|
+
const recs = [];
|
|
202
|
+
for (const sig of signals.slice(0, 10)) {
|
|
203
|
+
let action = "";
|
|
204
|
+
let reasoning = "";
|
|
205
|
+
let urgency = "monitor";
|
|
206
|
+
let category = "market";
|
|
207
|
+
if (sig.category === "funding") {
|
|
208
|
+
action = `Research ${sig.entity}'s funding round. Evaluate if this changes your competitive landscape.`;
|
|
209
|
+
reasoning = "Funding signals shift market dynamics. A well-funded competitor can accelerate faster.";
|
|
210
|
+
urgency = "this_week";
|
|
211
|
+
category = "competitive";
|
|
212
|
+
}
|
|
213
|
+
else if (sig.category === "launch") {
|
|
214
|
+
action = `Evaluate ${sig.entity}. Is this a competitor, partner opportunity, or irrelevant?`;
|
|
215
|
+
reasoning = "New launches in your space can validate or threaten your wedge.";
|
|
216
|
+
urgency = sig.severity === "flash" ? "act_now" : "this_week";
|
|
217
|
+
category = "opportunity";
|
|
218
|
+
}
|
|
219
|
+
else if (sig.category === "market" && sig.severity === "flash") {
|
|
220
|
+
action = `Check your exposure to ${sig.entity}. Review your portfolio and customer base.`;
|
|
221
|
+
reasoning = "Major market moves can affect your runway, fundraising, and customer behavior.";
|
|
222
|
+
urgency = "act_now";
|
|
223
|
+
category = "risk";
|
|
224
|
+
}
|
|
225
|
+
else if (sig.category === "trend") {
|
|
226
|
+
action = `Assess if the ${sig.entity} trend affects your product roadmap or positioning.`;
|
|
227
|
+
reasoning = "Trending topics signal where developer and investor attention is shifting.";
|
|
228
|
+
urgency = "this_week";
|
|
229
|
+
category = "opportunity";
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
action = `Note: ${sig.headline}`;
|
|
233
|
+
reasoning = "Signal detected but no immediate action required.";
|
|
234
|
+
urgency = "monitor";
|
|
235
|
+
category = "market";
|
|
236
|
+
}
|
|
237
|
+
recs.push({ signal: sig, action, reasoning, urgency, category });
|
|
238
|
+
}
|
|
239
|
+
// Sort: act_now first, then this_week, then monitor
|
|
240
|
+
const urgencyOrder = { act_now: 0, this_week: 1, monitor: 2 };
|
|
241
|
+
recs.sort((a, b) => urgencyOrder[a.urgency] - urgencyOrder[b.urgency]);
|
|
242
|
+
return recs;
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/sweep/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NodeBench Sweep Engine — Live signal intelligence layer.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: Crucix's 27-source parallel sweep + delta engine
|
|
5
|
+
* Architecture: Self-contained source modules, each exports collect()
|
|
6
|
+
*/
|
|
7
|
+
export type { SweepSignal, SweepResult, DeltaResult, SourceCollector } from "./types.js";
|
|
8
|
+
export { registerSource, runSweep, computeDelta, initSweepTables, getLatestSweep, getPreviousSweep, generateRecommendations } from "./engine.js";
|
|
9
|
+
export type { Recommendation } from "./engine.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NodeBench Sweep Engine — Live signal intelligence layer.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: Crucix's 27-source parallel sweep + delta engine
|
|
5
|
+
* Architecture: Self-contained source modules, each exports collect()
|
|
6
|
+
*/
|
|
7
|
+
export { registerSource, runSweep, computeDelta, initSweepTables, getLatestSweep, getPreviousSweep, generateRecommendations } from "./engine.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sweep/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Trending source — trending repos in AI/agent space.
|
|
3
|
+
* No API key needed. Scrapes the trending page.
|
|
4
|
+
*/
|
|
5
|
+
export async function collect() {
|
|
6
|
+
const signals = [];
|
|
7
|
+
try {
|
|
8
|
+
// Use GitHub's unofficial trending API endpoint
|
|
9
|
+
const resp = await fetch("https://api.github.com/search/repositories?q=stars:>100+pushed:>2026-03-25+topic:ai-agent+topic:mcp+topic:llm&sort=stars&order=desc&per_page=10", {
|
|
10
|
+
signal: AbortSignal.timeout(5000),
|
|
11
|
+
headers: { "Accept": "application/vnd.github.v3+json" },
|
|
12
|
+
});
|
|
13
|
+
if (!resp.ok)
|
|
14
|
+
return [];
|
|
15
|
+
const data = (await resp.json());
|
|
16
|
+
for (const repo of (data.items ?? []).slice(0, 10)) {
|
|
17
|
+
const entity = repo.full_name?.split("/")?.[1] ?? repo.name ?? "unknown";
|
|
18
|
+
const stars = repo.stargazers_count ?? 0;
|
|
19
|
+
const score = Math.min(100, Math.round(stars / 100));
|
|
20
|
+
signals.push({
|
|
21
|
+
id: `gh_${repo.id}`,
|
|
22
|
+
source: "github_trending",
|
|
23
|
+
entity,
|
|
24
|
+
headline: `${repo.full_name}: ${(repo.description ?? "").slice(0, 80)}`,
|
|
25
|
+
url: repo.html_url,
|
|
26
|
+
score,
|
|
27
|
+
category: "product",
|
|
28
|
+
severity: stars > 5000 ? "flash" : stars > 1000 ? "priority" : "routine",
|
|
29
|
+
metadata: { stars, forks: repo.forks_count, language: repo.language },
|
|
30
|
+
collectedAt: new Date().toISOString(),
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch { /* GitHub unavailable */ }
|
|
35
|
+
return signals;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=github_trending.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github_trending.js","sourceRoot":"","sources":["../../../src/sweep/sources/github_trending.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,CAAC,KAAK,UAAU,OAAO;IAC3B,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,IAAI,CAAC;QACH,gDAAgD;QAChD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,iJAAiJ,EAAE;YAC1K,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;YACjC,OAAO,EAAE,EAAE,QAAQ,EAAE,gCAAgC,EAAE;SACxD,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAQ,CAAC;QAExC,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YACnD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC;YACzE,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,IAAI,CAAC,CAAC;YACzC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC;YAErD,OAAO,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,MAAM,IAAI,CAAC,EAAE,EAAE;gBACnB,MAAM,EAAE,iBAAiB;gBACzB,MAAM;gBACN,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;gBACvE,GAAG,EAAE,IAAI,CAAC,QAAQ;gBAClB,KAAK;gBACL,QAAQ,EAAE,SAAS;gBACnB,QAAQ,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;gBACxE,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;gBACrE,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACtC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,wBAAwB,CAAC,CAAC;IACpC,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HackerNews source — top stories mentioning AI/agent/startup companies.
|
|
3
|
+
* No API key needed. Uses official HN Firebase API.
|
|
4
|
+
* Pattern: Crucix's self-contained source module with briefing() export.
|
|
5
|
+
*/
|
|
6
|
+
import type { SweepSignal } from "../types.js";
|
|
7
|
+
export declare function collect(): Promise<SweepSignal[]>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HackerNews source — top stories mentioning AI/agent/startup companies.
|
|
3
|
+
* No API key needed. Uses official HN Firebase API.
|
|
4
|
+
* Pattern: Crucix's self-contained source module with briefing() export.
|
|
5
|
+
*/
|
|
6
|
+
const HN_TOP_URL = "https://hacker-news.firebaseio.com/v0/topstories.json";
|
|
7
|
+
const HN_ITEM_URL = (id) => `https://hacker-news.firebaseio.com/v0/item/${id}.json`;
|
|
8
|
+
// AI/agent/startup keywords that matter to founders
|
|
9
|
+
const SIGNAL_KEYWORDS = /\b(AI|GPT|Claude|Anthropic|OpenAI|LLM|agent|MCP|startup|YC|funding|Series [A-D]|acquisition|IPO|valuation|launch|open.?source|developer tool|API|infra|vector|RAG|fine.?tun)/i;
|
|
10
|
+
export async function collect() {
|
|
11
|
+
const signals = [];
|
|
12
|
+
try {
|
|
13
|
+
const resp = await fetch(HN_TOP_URL, { signal: AbortSignal.timeout(5000) });
|
|
14
|
+
if (!resp.ok)
|
|
15
|
+
return [];
|
|
16
|
+
const ids = (await resp.json());
|
|
17
|
+
// Fetch top 30 stories in parallel
|
|
18
|
+
const items = await Promise.all(ids.slice(0, 30).map(async (id) => {
|
|
19
|
+
try {
|
|
20
|
+
const r = await fetch(HN_ITEM_URL(id), { signal: AbortSignal.timeout(3000) });
|
|
21
|
+
return r.ok ? await r.json() : null;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}));
|
|
27
|
+
for (const item of items) {
|
|
28
|
+
if (!item?.title)
|
|
29
|
+
continue;
|
|
30
|
+
if (!SIGNAL_KEYWORDS.test(item.title))
|
|
31
|
+
continue;
|
|
32
|
+
// Extract entity from title
|
|
33
|
+
const entityMatch = item.title.match(/([A-Z][a-zA-Z]+(?:\s+[A-Z][a-zA-Z]+)*)/);
|
|
34
|
+
const entity = entityMatch?.[0] ?? item.title.split(/[:\-–—]/).map((s) => s.trim())[0].slice(0, 30);
|
|
35
|
+
const score = Math.min(100, Math.round((item.score ?? 0) / 5));
|
|
36
|
+
const severity = score > 60 ? "flash" : score > 30 ? "priority" : "routine";
|
|
37
|
+
signals.push({
|
|
38
|
+
id: `hn_${item.id}`,
|
|
39
|
+
source: "hackernews",
|
|
40
|
+
entity,
|
|
41
|
+
headline: item.title.slice(0, 120),
|
|
42
|
+
url: item.url ?? `https://news.ycombinator.com/item?id=${item.id}`,
|
|
43
|
+
score,
|
|
44
|
+
category: /fund|rais|series|valuation/i.test(item.title) ? "funding"
|
|
45
|
+
: /launch|ship|release|announce/i.test(item.title) ? "launch"
|
|
46
|
+
: /acqui|merge|IPO/i.test(item.title) ? "market"
|
|
47
|
+
: "trend",
|
|
48
|
+
severity,
|
|
49
|
+
metadata: { points: item.score, comments: item.descendants },
|
|
50
|
+
collectedAt: new Date().toISOString(),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch { /* HN unavailable — non-fatal */ }
|
|
55
|
+
return signals;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=hackernews.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hackernews.js","sourceRoot":"","sources":["../../../src/sweep/sources/hackernews.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenBB-style financial data source.
|
|
3
|
+
* Uses free Yahoo Finance API (same pattern as OpenBB's data providers).
|
|
4
|
+
* No API key needed.
|
|
5
|
+
*
|
|
6
|
+
* Tracks: major AI/tech company fundamentals that founders care about.
|
|
7
|
+
*/
|
|
8
|
+
import type { SweepSignal } from "../types.js";
|
|
9
|
+
export declare function collect(): Promise<SweepSignal[]>;
|