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
package/README.md
CHANGED
|
@@ -5,69 +5,125 @@
|
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](https://github.com/HomenShum/nodebench-ai)
|
|
7
7
|
[](https://modelcontextprotocol.io)
|
|
8
|
-
[](https://www.npmjs.com/package/nodebench-mcp)
|
|
9
9
|
|
|
10
|
-
**
|
|
10
|
+
**Investigate a topic and return a sourced report fast.** NodeBench MCP now defaults to a small workflow facade, with heavier research and admin surfaces moved behind explicit presets.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Default install: `19` visible tools total, including `7` core workflow tools:
|
|
13
|
+
`investigate`, `compare`, `track`, `summarize`, `search`, `report`, and `ask_context`.
|
|
13
14
|
|
|
14
15
|
```bash
|
|
15
|
-
#
|
|
16
|
+
# Default v3 core workflow surface
|
|
16
17
|
claude mcp add nodebench -- npx -y nodebench-mcp
|
|
17
18
|
|
|
18
|
-
#
|
|
19
|
-
claude mcp add nodebench -- npx -y nodebench-mcp --preset
|
|
19
|
+
# Extended workflow surface
|
|
20
|
+
claude mcp add nodebench -- npx -y nodebench-mcp --preset power
|
|
20
21
|
|
|
21
|
-
#
|
|
22
|
-
claude mcp add nodebench -- npx -y nodebench-mcp --preset
|
|
22
|
+
# Admin/runtime surface
|
|
23
|
+
claude mcp add nodebench -- npx -y nodebench-mcp --preset admin --admin
|
|
23
24
|
```
|
|
24
25
|
|
|
26
|
+
### What's New
|
|
27
|
+
|
|
28
|
+
- **v3 default surface** — the default preset is now a workflow-first facade instead of a tool warehouse.
|
|
29
|
+
- **Admin-only runtime gates** — dashboards and the observability watchdog no longer start on the default hot path. Use `--admin`, `--dashboards`, or `--watchdog` explicitly.
|
|
30
|
+
- **Faster health path** — `--health` now loads only the active preset instead of eagerly loading every domain.
|
|
31
|
+
- **Power and admin presets** — heavier research and operator lanes are still available, but no longer define the front door.
|
|
32
|
+
|
|
33
|
+
> **New here?** Read **[AGENT_LOGIC.md](./AGENT_LOGIC.md)** for the complete guide to how NodeBench thinks.
|
|
34
|
+
|
|
25
35
|
---
|
|
26
36
|
|
|
27
|
-
##
|
|
37
|
+
## RETHINK REDESIGN APR 2026
|
|
28
38
|
|
|
29
|
-
|
|
39
|
+
This section records a repo-grounded reexamination of NodeBench MCP as of April 2026. It is intentionally blunt. The goal is to shrink the product to clear, measurable workflows and make the runtime and claims trustworthy.
|
|
30
40
|
|
|
31
|
-
###
|
|
41
|
+
### Repo-grounded findings
|
|
32
42
|
|
|
33
|
-
|
|
43
|
+
- **Surface area and messaging are out of sync**
|
|
44
|
+
- This README currently markets `350+ tools`, `founder` under `50` tools, and `full` as `338`.
|
|
45
|
+
- The audit that drove this section measured roughly `28` tools in the starter `tools/list` payload, roughly `186` in `founder`, and roughly `546` in `full`, before counting the extra dynamic-loading helpers separately.
|
|
46
|
+
- **The core executable is overloaded**
|
|
47
|
+
- `packages/mcp-local/src/index.ts` currently combines MCP serving, analytics tracking, embedding bootstrapping, profiling hooks, A/B instrumentation, dynamic tool loading, dashboard startup, and engine hosting in one runtime path.
|
|
48
|
+
- **Performance is not yet credibly measured**
|
|
49
|
+
- During this audit, `node packages/mcp-local/dist/index.js --health` took about `2.9s` locally because CLI mode eagerly loaded all toolsets before exit.
|
|
50
|
+
- The main performance comparison in the package measures local toolchain overhead, not end-user outcome quality, startup SLOs, workflow completion, or real provider spend.
|
|
51
|
+
- **Cost reporting is not yet auditable**
|
|
52
|
+
- The current profiler relies on heuristic per-tool cost estimates, not authoritative provider billing or exact token accounting.
|
|
53
|
+
- **Workflow clarity is weak**
|
|
54
|
+
- The product currently explains presets, domains, discovery engines, and meta-systems before it proves one concrete job to be done.
|
|
34
55
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
56
|
+
### Redesign principles
|
|
57
|
+
|
|
58
|
+
1. **One dominant workflow per persona**
|
|
59
|
+
- A founder should land on one obvious path.
|
|
60
|
+
- A banker should land on one obvious path.
|
|
61
|
+
- The MCP should prove value before it explains its architecture.
|
|
62
|
+
2. **Truthful counts and truthful claims**
|
|
63
|
+
- Preset docs, README counts, and `tools/list` output must agree.
|
|
64
|
+
3. **Speed is a product behavior**
|
|
65
|
+
- Measure startup time, `tools/list` payload size, per-tool latency, and workflow time-to-first-value.
|
|
66
|
+
4. **Keep optional systems out of the hot path**
|
|
67
|
+
- Embeddings, dashboards, profilers, and engine surfaces should not make the default MCP startup slower.
|
|
68
|
+
5. **Prefer workflows over catalogs**
|
|
69
|
+
- Opinionated, repeatable outcomes are more valuable than an oversized flat tool inventory.
|
|
70
|
+
6. **Ship process, not prose**
|
|
71
|
+
- The right mental model is a small number of strong workflows with evidence and verification, not a giant capabilities brochure.
|
|
72
|
+
|
|
73
|
+
### Execution board
|
|
74
|
+
|
|
75
|
+
| Ship order | Cause | Symptom in NodeBench | Metric to enforce |
|
|
76
|
+
| --- | --- | --- | --- |
|
|
77
|
+
| 1 | No single dominant job | The package reads like "everything MCP" instead of one clear wedge | Every persona entry point must answer the main job in one sentence |
|
|
78
|
+
| 2 | Tool surface is not truthful | README counts and runtime counts disagree | Published counts must match `tools/list` within 5% |
|
|
79
|
+
| 3 | Workflow is hidden behind tool volume | Users see presets, domains, and discovery systems before a clear task path | One canonical workflow per persona, completable in 3 to 5 tool calls |
|
|
80
|
+
| 4 | Performance is claimed, not instrumented | Benchmarks focus on harness overhead, not real user value | Track startup p50/p95, `tools/list` bytes, per-tool latency, workflow success, and real spend |
|
|
81
|
+
| 5 | Hot path contains optional systems | Profiling, embeddings, dashboards, and engine behavior sit in the main boot path | `--health` under 300ms and stdio ready under 500ms on warm start |
|
|
82
|
+
| 6 | Benchmarking is inward-facing | The package proves bookkeeping more than business outcomes | Benchmark by artifact quality, time-to-artifact, cost-per-artifact, and reuse rate |
|
|
83
|
+
|
|
84
|
+
### Reference models
|
|
85
|
+
|
|
86
|
+
- **[agent-skills](https://github.com/addyosmani/agent-skills)**: process, not prose. Strong lifecycle commands, checkpoints, and evidence requirements.
|
|
87
|
+
- **[GitHub MCP Server](https://github.com/github/github-mcp-server)**: narrower toolsets improve tool choice and reduce context size. The server also exposes a simple `tool-search` utility.
|
|
88
|
+
- **[Google MCP Toolbox](https://github.com/googleapis/mcp-toolbox)**: performance and operability are anchored in concrete runtime primitives such as connection pooling and OpenTelemetry, not only internal heuristics.
|
|
89
|
+
|
|
90
|
+
### Bottom line
|
|
40
91
|
|
|
41
|
-
|
|
92
|
+
NodeBench MCP should evolve from a monolithic "hundreds of tools" surface into a smaller number of opinionated workflow products backed by a measurable, trustworthy runtime.
|
|
42
93
|
|
|
43
|
-
|
|
44
|
-
|---|---|---|---|
|
|
45
|
-
| `founder` | ~40 | Company tracking, session memory, local dashboard, weekly reset, delegation briefs | Solo founders, CEOs making daily decisions |
|
|
46
|
-
| `banker` | ~39 | Company profiling, web research, recon, risk assessment | Due diligence, deal evaluation, market analysis |
|
|
47
|
-
| `operator` | ~40 | Company tracking, causal memory, action tracing, important-change review | COOs, ops leads tracking execution |
|
|
48
|
-
| `researcher` | ~32 | Web search, recon, session memory | Analysts, research-heavy workflows |
|
|
94
|
+
Unified cross-surface spec: [`docs/architecture/UNIFIED_WORKFLOW_SPEC.md`](../../docs/architecture/UNIFIED_WORKFLOW_SPEC.md)
|
|
49
95
|
|
|
50
|
-
|
|
96
|
+
Production companion spec: [`docs/architecture/UNIFIED_WEB_MCP_PRODUCTION_SPEC.md`](../../docs/architecture/UNIFIED_WEB_MCP_PRODUCTION_SPEC.md)
|
|
51
97
|
|
|
52
|
-
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## What You Get
|
|
101
|
+
|
|
102
|
+
NodeBench is now a workflow-first MCP. The default install proves one concrete job quickly, and the heavier surfaces are still available when you explicitly ask for them.
|
|
103
|
+
|
|
104
|
+
### Presets
|
|
105
|
+
|
|
106
|
+
| Preset | Visible tools | What it is for |
|
|
53
107
|
|---|---|---|
|
|
54
|
-
| `
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
108
|
+
| `default` | `19` | v3 core workflow facade: investigate, compare, track, summarize, search, report, ask_context, plus discovery/meta helpers |
|
|
109
|
+
| `power` | `203` | Extended research and founder workflow pack without auto-starting admin runtime surfaces |
|
|
110
|
+
| `admin` | `106` | Profiling, observability, dashboards, eval, and debug-oriented operator lanes |
|
|
111
|
+
| `founder` | `191` | Legacy founder preset kept for compatibility |
|
|
112
|
+
| `full` | all domains | Maximum coverage when you explicitly want the warehouse |
|
|
113
|
+
|
|
114
|
+
### Default workflow
|
|
115
|
+
|
|
116
|
+
```text
|
|
117
|
+
ASK -> CHECK -> WRITE -> SAVE
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The default preset is optimized for that loop. It does not start local dashboards or the observability watchdog unless you pass admin flags explicitly.
|
|
65
121
|
|
|
66
122
|
```bash
|
|
67
123
|
# Claude Code
|
|
68
|
-
claude mcp add nodebench -- npx -y nodebench-mcp
|
|
124
|
+
claude mcp add nodebench -- npx -y nodebench-mcp
|
|
69
125
|
|
|
70
|
-
# Windsurf / Cursor — add --preset to args in your MCP config
|
|
126
|
+
# Windsurf / Cursor — add --preset to args in your MCP config when you want more than the default workflow surface
|
|
71
127
|
```
|
|
72
128
|
|
|
73
129
|
---
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* alertRouter.ts — Multi-channel alert delivery (Crucix pattern).
|
|
3
|
+
*
|
|
4
|
+
* Routes sweep signals to Telegram, Discord, Slack, or webhooks
|
|
5
|
+
* based on severity tier (FLASH/PRIORITY/ROUTINE).
|
|
6
|
+
*
|
|
7
|
+
* Setup: set env vars for the channels you want:
|
|
8
|
+
* - TELEGRAM_BOT_TOKEN + TELEGRAM_CHAT_ID
|
|
9
|
+
* - DISCORD_WEBHOOK_URL
|
|
10
|
+
* - SLACK_WEBHOOK_URL
|
|
11
|
+
* - ALERT_WEBHOOK_URL (generic)
|
|
12
|
+
*/
|
|
13
|
+
import type { SweepSignal } from "../sweep/types.js";
|
|
14
|
+
export interface AlertConfig {
|
|
15
|
+
telegram?: {
|
|
16
|
+
botToken: string;
|
|
17
|
+
chatId: string;
|
|
18
|
+
};
|
|
19
|
+
discord?: {
|
|
20
|
+
webhookUrl: string;
|
|
21
|
+
};
|
|
22
|
+
slack?: {
|
|
23
|
+
webhookUrl: string;
|
|
24
|
+
};
|
|
25
|
+
generic?: {
|
|
26
|
+
webhookUrl: string;
|
|
27
|
+
};
|
|
28
|
+
minSeverity: "flash" | "priority" | "routine";
|
|
29
|
+
}
|
|
30
|
+
export declare function getAlertConfig(): AlertConfig;
|
|
31
|
+
export declare function sendAlert(signal: SweepSignal, config?: AlertConfig): Promise<{
|
|
32
|
+
sent: string[];
|
|
33
|
+
failed: string[];
|
|
34
|
+
}>;
|
|
35
|
+
export declare function alertOnNewSignals(signals: SweepSignal[]): Promise<{
|
|
36
|
+
alertsSent: number;
|
|
37
|
+
channels: string[];
|
|
38
|
+
}>;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* alertRouter.ts — Multi-channel alert delivery (Crucix pattern).
|
|
3
|
+
*
|
|
4
|
+
* Routes sweep signals to Telegram, Discord, Slack, or webhooks
|
|
5
|
+
* based on severity tier (FLASH/PRIORITY/ROUTINE).
|
|
6
|
+
*
|
|
7
|
+
* Setup: set env vars for the channels you want:
|
|
8
|
+
* - TELEGRAM_BOT_TOKEN + TELEGRAM_CHAT_ID
|
|
9
|
+
* - DISCORD_WEBHOOK_URL
|
|
10
|
+
* - SLACK_WEBHOOK_URL
|
|
11
|
+
* - ALERT_WEBHOOK_URL (generic)
|
|
12
|
+
*/
|
|
13
|
+
export function getAlertConfig() {
|
|
14
|
+
return {
|
|
15
|
+
telegram: process.env.TELEGRAM_BOT_TOKEN && process.env.TELEGRAM_CHAT_ID
|
|
16
|
+
? { botToken: process.env.TELEGRAM_BOT_TOKEN, chatId: process.env.TELEGRAM_CHAT_ID }
|
|
17
|
+
: undefined,
|
|
18
|
+
discord: process.env.DISCORD_WEBHOOK_URL
|
|
19
|
+
? { webhookUrl: process.env.DISCORD_WEBHOOK_URL }
|
|
20
|
+
: undefined,
|
|
21
|
+
slack: process.env.SLACK_WEBHOOK_URL
|
|
22
|
+
? { webhookUrl: process.env.SLACK_WEBHOOK_URL }
|
|
23
|
+
: undefined,
|
|
24
|
+
generic: process.env.ALERT_WEBHOOK_URL
|
|
25
|
+
? { webhookUrl: process.env.ALERT_WEBHOOK_URL }
|
|
26
|
+
: undefined,
|
|
27
|
+
minSeverity: process.env.ALERT_MIN_SEVERITY ?? "priority",
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const SEV_ORDER = { flash: 3, priority: 2, routine: 1 };
|
|
31
|
+
function shouldAlert(signal, config) {
|
|
32
|
+
return SEV_ORDER[signal.severity] >= SEV_ORDER[config.minSeverity];
|
|
33
|
+
}
|
|
34
|
+
function formatMessage(signal) {
|
|
35
|
+
const emoji = signal.severity === "flash" ? "🔴" : signal.severity === "priority" ? "🟡" : "🔵";
|
|
36
|
+
return `${emoji} [${signal.severity.toUpperCase()}] ${signal.entity}\n${signal.headline}${signal.url ? `\n${signal.url}` : ""}`;
|
|
37
|
+
}
|
|
38
|
+
export async function sendAlert(signal, config) {
|
|
39
|
+
const cfg = config ?? getAlertConfig();
|
|
40
|
+
if (!shouldAlert(signal, cfg))
|
|
41
|
+
return { sent: [], failed: [] };
|
|
42
|
+
const msg = formatMessage(signal);
|
|
43
|
+
const sent = [];
|
|
44
|
+
const failed = [];
|
|
45
|
+
// Telegram
|
|
46
|
+
if (cfg.telegram) {
|
|
47
|
+
try {
|
|
48
|
+
const resp = await fetch(`https://api.telegram.org/bot${cfg.telegram.botToken}/sendMessage`, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: { "Content-Type": "application/json" },
|
|
51
|
+
body: JSON.stringify({ chat_id: cfg.telegram.chatId, text: msg, parse_mode: "Markdown" }),
|
|
52
|
+
signal: AbortSignal.timeout(5000),
|
|
53
|
+
});
|
|
54
|
+
if (resp.ok)
|
|
55
|
+
sent.push("telegram");
|
|
56
|
+
else
|
|
57
|
+
failed.push("telegram");
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
failed.push("telegram");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Discord webhook
|
|
64
|
+
if (cfg.discord) {
|
|
65
|
+
try {
|
|
66
|
+
const color = signal.severity === "flash" ? 0xFF0000 : signal.severity === "priority" ? 0xFFAA00 : 0x0088FF;
|
|
67
|
+
const resp = await fetch(cfg.discord.webhookUrl, {
|
|
68
|
+
method: "POST",
|
|
69
|
+
headers: { "Content-Type": "application/json" },
|
|
70
|
+
body: JSON.stringify({
|
|
71
|
+
embeds: [{ title: `${signal.entity} — ${signal.severity.toUpperCase()}`, description: signal.headline, url: signal.url, color }],
|
|
72
|
+
}),
|
|
73
|
+
signal: AbortSignal.timeout(5000),
|
|
74
|
+
});
|
|
75
|
+
if (resp.ok)
|
|
76
|
+
sent.push("discord");
|
|
77
|
+
else
|
|
78
|
+
failed.push("discord");
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
failed.push("discord");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Slack webhook
|
|
85
|
+
if (cfg.slack) {
|
|
86
|
+
try {
|
|
87
|
+
const resp = await fetch(cfg.slack.webhookUrl, {
|
|
88
|
+
method: "POST",
|
|
89
|
+
headers: { "Content-Type": "application/json" },
|
|
90
|
+
body: JSON.stringify({ text: msg }),
|
|
91
|
+
signal: AbortSignal.timeout(5000),
|
|
92
|
+
});
|
|
93
|
+
if (resp.ok)
|
|
94
|
+
sent.push("slack");
|
|
95
|
+
else
|
|
96
|
+
failed.push("slack");
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
failed.push("slack");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Generic webhook
|
|
103
|
+
if (cfg.generic) {
|
|
104
|
+
try {
|
|
105
|
+
const resp = await fetch(cfg.generic.webhookUrl, {
|
|
106
|
+
method: "POST",
|
|
107
|
+
headers: { "Content-Type": "application/json" },
|
|
108
|
+
body: JSON.stringify({ signal, message: msg }),
|
|
109
|
+
signal: AbortSignal.timeout(5000),
|
|
110
|
+
});
|
|
111
|
+
if (resp.ok)
|
|
112
|
+
sent.push("generic");
|
|
113
|
+
else
|
|
114
|
+
failed.push("generic");
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
failed.push("generic");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return { sent, failed };
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Send alerts for all signals above the severity threshold.
|
|
124
|
+
* Deduplicates by signal ID (Crucix semantic dedup pattern).
|
|
125
|
+
*/
|
|
126
|
+
const sentAlertIds = new Set();
|
|
127
|
+
const MAX_SENT_CACHE = 500;
|
|
128
|
+
export async function alertOnNewSignals(signals) {
|
|
129
|
+
const config = getAlertConfig();
|
|
130
|
+
let alertsSent = 0;
|
|
131
|
+
const channels = new Set();
|
|
132
|
+
for (const signal of signals) {
|
|
133
|
+
if (sentAlertIds.has(signal.id))
|
|
134
|
+
continue; // Dedup
|
|
135
|
+
if (!shouldAlert(signal, config))
|
|
136
|
+
continue;
|
|
137
|
+
const result = await sendAlert(signal, config);
|
|
138
|
+
if (result.sent.length > 0) {
|
|
139
|
+
alertsSent++;
|
|
140
|
+
sentAlertIds.add(signal.id);
|
|
141
|
+
result.sent.forEach(c => channels.add(c));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Bounded dedup cache
|
|
145
|
+
if (sentAlertIds.size > MAX_SENT_CACHE) {
|
|
146
|
+
const toDelete = [...sentAlertIds].slice(0, sentAlertIds.size - MAX_SENT_CACHE);
|
|
147
|
+
toDelete.forEach(id => sentAlertIds.delete(id));
|
|
148
|
+
}
|
|
149
|
+
return { alertsSent, channels: [...channels] };
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=alertRouter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alertRouter.js","sourceRoot":"","sources":["../../src/agents/alertRouter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* entityMemory.ts — Long-term entity knowledge store (DeerFlow pattern).
|
|
3
|
+
*
|
|
4
|
+
* Stores entity snapshots across sessions. Enables:
|
|
5
|
+
* - "Anthropic was at $14B revenue last time you checked"
|
|
6
|
+
* - "Market share changed from 40% to 70% since your last search"
|
|
7
|
+
* - Drift detection between snapshots
|
|
8
|
+
*/
|
|
9
|
+
export interface EntitySnapshot {
|
|
10
|
+
id: string;
|
|
11
|
+
entityName: string;
|
|
12
|
+
confidence: number;
|
|
13
|
+
answer: string;
|
|
14
|
+
signalCount: number;
|
|
15
|
+
riskCount: number;
|
|
16
|
+
comparableCount: number;
|
|
17
|
+
sourceCount: number;
|
|
18
|
+
keyMetrics: Record<string, string>;
|
|
19
|
+
timestamp: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function initEntityMemoryTables(): void;
|
|
22
|
+
export declare function saveEntitySnapshot(data: {
|
|
23
|
+
entityName: string;
|
|
24
|
+
confidence: number;
|
|
25
|
+
answer: string;
|
|
26
|
+
signalCount: number;
|
|
27
|
+
riskCount: number;
|
|
28
|
+
comparableCount: number;
|
|
29
|
+
sourceCount: number;
|
|
30
|
+
keyMetrics?: Record<string, string>;
|
|
31
|
+
}): string;
|
|
32
|
+
export declare function getEntityHistory(entityName: string, limit?: number): EntitySnapshot[];
|
|
33
|
+
export declare function detectEntityDrift(entityName: string): {
|
|
34
|
+
hasDrift: boolean;
|
|
35
|
+
previousConfidence?: number;
|
|
36
|
+
currentConfidence?: number;
|
|
37
|
+
confidenceDelta?: number;
|
|
38
|
+
previousAnswer?: string;
|
|
39
|
+
daysSinceLastCheck?: number;
|
|
40
|
+
} | null;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* entityMemory.ts — Long-term entity knowledge store (DeerFlow pattern).
|
|
3
|
+
*
|
|
4
|
+
* Stores entity snapshots across sessions. Enables:
|
|
5
|
+
* - "Anthropic was at $14B revenue last time you checked"
|
|
6
|
+
* - "Market share changed from 40% to 70% since your last search"
|
|
7
|
+
* - Drift detection between snapshots
|
|
8
|
+
*/
|
|
9
|
+
import { getDb, genId } from "../db.js";
|
|
10
|
+
export function initEntityMemoryTables() {
|
|
11
|
+
const db = getDb();
|
|
12
|
+
db.exec(`
|
|
13
|
+
CREATE TABLE IF NOT EXISTS entity_snapshots (
|
|
14
|
+
id TEXT PRIMARY KEY,
|
|
15
|
+
entity_name TEXT NOT NULL,
|
|
16
|
+
confidence REAL DEFAULT 0,
|
|
17
|
+
answer TEXT,
|
|
18
|
+
signal_count INTEGER DEFAULT 0,
|
|
19
|
+
risk_count INTEGER DEFAULT 0,
|
|
20
|
+
comparable_count INTEGER DEFAULT 0,
|
|
21
|
+
source_count INTEGER DEFAULT 0,
|
|
22
|
+
key_metrics TEXT DEFAULT '{}',
|
|
23
|
+
timestamp TEXT NOT NULL
|
|
24
|
+
);
|
|
25
|
+
CREATE INDEX IF NOT EXISTS idx_es_entity ON entity_snapshots(entity_name, timestamp);
|
|
26
|
+
`);
|
|
27
|
+
}
|
|
28
|
+
export function saveEntitySnapshot(data) {
|
|
29
|
+
const db = getDb();
|
|
30
|
+
const id = genId("esnap");
|
|
31
|
+
db.prepare(`
|
|
32
|
+
INSERT INTO entity_snapshots (id, entity_name, confidence, answer, signal_count, risk_count, comparable_count, source_count, key_metrics, timestamp)
|
|
33
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
34
|
+
`).run(id, data.entityName, data.confidence, data.answer?.slice(0, 500), data.signalCount, data.riskCount, data.comparableCount, data.sourceCount, JSON.stringify(data.keyMetrics ?? {}), new Date().toISOString());
|
|
35
|
+
return id;
|
|
36
|
+
}
|
|
37
|
+
export function getEntityHistory(entityName, limit = 10) {
|
|
38
|
+
const db = getDb();
|
|
39
|
+
return db.prepare(`
|
|
40
|
+
SELECT * FROM entity_snapshots WHERE entity_name = ? ORDER BY timestamp DESC LIMIT ?
|
|
41
|
+
`).all(entityName, limit).map(r => ({
|
|
42
|
+
id: r.id, entityName: r.entity_name, confidence: r.confidence,
|
|
43
|
+
answer: r.answer, signalCount: r.signal_count, riskCount: r.risk_count,
|
|
44
|
+
comparableCount: r.comparable_count, sourceCount: r.source_count,
|
|
45
|
+
keyMetrics: JSON.parse(r.key_metrics ?? "{}"), timestamp: r.timestamp,
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
export function detectEntityDrift(entityName) {
|
|
49
|
+
const history = getEntityHistory(entityName, 2);
|
|
50
|
+
if (history.length < 2)
|
|
51
|
+
return null;
|
|
52
|
+
const [current, previous] = history;
|
|
53
|
+
const daysDiff = (new Date(current.timestamp).getTime() - new Date(previous.timestamp).getTime()) / 86400000;
|
|
54
|
+
const confDelta = current.confidence - previous.confidence;
|
|
55
|
+
return {
|
|
56
|
+
hasDrift: Math.abs(confDelta) > 10 || daysDiff > 7,
|
|
57
|
+
previousConfidence: previous.confidence,
|
|
58
|
+
currentConfidence: current.confidence,
|
|
59
|
+
confidenceDelta: Math.round(confDelta),
|
|
60
|
+
previousAnswer: previous.answer?.slice(0, 200),
|
|
61
|
+
daysSinceLastCheck: Math.round(daysDiff),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=entityMemory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entityMemory.js","sourceRoot":"","sources":["../../src/agents/entityMemory.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAexC,MAAM,UAAU,sBAAsB;IACpC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;GAcP,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IASlC;IACC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1B,EAAE,CAAC,OAAO,CAAC;;;GAGV,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EACrE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,WAAW,EACxE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IACnE,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,UAAkB,EAAE,QAAgB,EAAE;IACrE,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,OAAQ,EAAE,CAAC,OAAO,CAAC;;GAElB,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC5C,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU;QAC7D,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC,UAAU;QACtE,eAAe,EAAE,CAAC,CAAC,gBAAgB,EAAE,WAAW,EAAE,CAAC,CAAC,YAAY;QAChE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,IAAI,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS;KACtE,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAQlD,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAChD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC;IACpC,MAAM,QAAQ,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,QAAQ,CAAC;IAC7G,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC;IAE3D,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,QAAQ,GAAG,CAAC;QAClD,kBAAkB,EAAE,QAAQ,CAAC,UAAU;QACvC,iBAAiB,EAAE,OAAO,CAAC,UAAU;QACrC,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;QACtC,cAAc,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;QAC9C,kBAAkB,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;KACzC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* subAgents.ts — Named specialist agents (DeerFlow pattern).
|
|
3
|
+
*
|
|
4
|
+
* Instead of flat tool dispatch, the harness can dispatch to specialist
|
|
5
|
+
* agents that each own a domain of tools and context.
|
|
6
|
+
*
|
|
7
|
+
* Agents:
|
|
8
|
+
* - ResearchAgent: web_search, linkup, recon, sweep
|
|
9
|
+
* - AnalysisAgent: extract_variables, build_claim_graph, countermodels
|
|
10
|
+
* - SynthesisAgent: render_decision_memo, export_artifact
|
|
11
|
+
* - ProfilerAgent: log_tool_call, suggest_optimizations
|
|
12
|
+
*/
|
|
13
|
+
export interface SubAgent {
|
|
14
|
+
name: string;
|
|
15
|
+
role: string;
|
|
16
|
+
tools: string[];
|
|
17
|
+
systemPrompt: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const RESEARCH_AGENT: SubAgent;
|
|
20
|
+
export declare const ANALYSIS_AGENT: SubAgent;
|
|
21
|
+
export declare const SYNTHESIS_AGENT: SubAgent;
|
|
22
|
+
export declare const PROFILER_AGENT: SubAgent;
|
|
23
|
+
export declare const ALL_AGENTS: SubAgent[];
|
|
24
|
+
/**
|
|
25
|
+
* Select the best agent for a given task based on tool requirements.
|
|
26
|
+
*/
|
|
27
|
+
export declare function selectAgent(toolName: string): SubAgent | null;
|
|
28
|
+
/**
|
|
29
|
+
* Plan a multi-agent workflow for a complex query.
|
|
30
|
+
* Returns ordered agent assignments.
|
|
31
|
+
*/
|
|
32
|
+
export declare function planAgentWorkflow(toolChain: string[]): Array<{
|
|
33
|
+
agent: SubAgent;
|
|
34
|
+
tools: string[];
|
|
35
|
+
}>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* subAgents.ts — Named specialist agents (DeerFlow pattern).
|
|
3
|
+
*
|
|
4
|
+
* Instead of flat tool dispatch, the harness can dispatch to specialist
|
|
5
|
+
* agents that each own a domain of tools and context.
|
|
6
|
+
*
|
|
7
|
+
* Agents:
|
|
8
|
+
* - ResearchAgent: web_search, linkup, recon, sweep
|
|
9
|
+
* - AnalysisAgent: extract_variables, build_claim_graph, countermodels
|
|
10
|
+
* - SynthesisAgent: render_decision_memo, export_artifact
|
|
11
|
+
* - ProfilerAgent: log_tool_call, suggest_optimizations
|
|
12
|
+
*/
|
|
13
|
+
export const RESEARCH_AGENT = {
|
|
14
|
+
name: "ResearchAgent",
|
|
15
|
+
role: "Gather intelligence from web, databases, and local context",
|
|
16
|
+
tools: ["web_search", "linkup_search", "run_recon", "enrich_entity", "founder_local_gather", "run_signal_sweep"],
|
|
17
|
+
systemPrompt: "You are a research agent. Gather comprehensive intelligence about the target entity. Search multiple sources in parallel. Return structured findings with sources, confidence scores, and key data points.",
|
|
18
|
+
};
|
|
19
|
+
export const ANALYSIS_AGENT = {
|
|
20
|
+
name: "AnalysisAgent",
|
|
21
|
+
role: "Analyze gathered data — extract variables, build claim graphs, generate counter-models",
|
|
22
|
+
tools: ["extract_variables", "build_claim_graph", "generate_countermodels", "rank_interventions", "score_compounding"],
|
|
23
|
+
systemPrompt: "You are an analysis agent. Take raw research data and extract structured intelligence: key variables with direction/impact, claims with evidence chains, alternative explanations, and ranked interventions.",
|
|
24
|
+
};
|
|
25
|
+
export const SYNTHESIS_AGENT = {
|
|
26
|
+
name: "SynthesisAgent",
|
|
27
|
+
role: "Combine analysis into decision-ready packets, memos, and briefs",
|
|
28
|
+
tools: ["render_decision_memo", "export_artifact_packet", "founder_local_synthesize", "founder_direction_assessment"],
|
|
29
|
+
systemPrompt: "You are a synthesis agent. Take analyzed intelligence and produce decision-ready artifacts: executive summaries, VC scorecards, risk registers, competitive landscapes, and actionable next steps.",
|
|
30
|
+
};
|
|
31
|
+
export const PROFILER_AGENT = {
|
|
32
|
+
name: "ProfilerAgent",
|
|
33
|
+
role: "Monitor execution, log costs, suggest optimizations",
|
|
34
|
+
tools: ["log_tool_call", "get_session_profile", "suggest_optimizations", "get_usage_insights"],
|
|
35
|
+
systemPrompt: "You are a profiler agent. Monitor every tool call for cost, latency, and redundancy. Suggest cheaper valid paths and reusable workflow templates.",
|
|
36
|
+
};
|
|
37
|
+
export const ALL_AGENTS = [RESEARCH_AGENT, ANALYSIS_AGENT, SYNTHESIS_AGENT, PROFILER_AGENT];
|
|
38
|
+
/**
|
|
39
|
+
* Select the best agent for a given task based on tool requirements.
|
|
40
|
+
*/
|
|
41
|
+
export function selectAgent(toolName) {
|
|
42
|
+
return ALL_AGENTS.find(a => a.tools.includes(toolName)) ?? null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Plan a multi-agent workflow for a complex query.
|
|
46
|
+
* Returns ordered agent assignments.
|
|
47
|
+
*/
|
|
48
|
+
export function planAgentWorkflow(toolChain) {
|
|
49
|
+
const assignments = new Map();
|
|
50
|
+
for (const tool of toolChain) {
|
|
51
|
+
const agent = selectAgent(tool);
|
|
52
|
+
const agentName = agent?.name ?? "HarnessDefault";
|
|
53
|
+
if (!assignments.has(agentName))
|
|
54
|
+
assignments.set(agentName, []);
|
|
55
|
+
assignments.get(agentName).push(tool);
|
|
56
|
+
}
|
|
57
|
+
return Array.from(assignments.entries()).map(([name, tools]) => ({
|
|
58
|
+
agent: ALL_AGENTS.find(a => a.name === name) ?? RESEARCH_AGENT,
|
|
59
|
+
tools,
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=subAgents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subAgents.js","sourceRoot":"","sources":["../../src/agents/subAgents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,MAAM,CAAC,MAAM,cAAc,GAAa;IACtC,IAAI,EAAE,eAAe;IACrB,IAAI,EAAE,4DAA4D;IAClE,KAAK,EAAE,CAAC,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,sBAAsB,EAAE,kBAAkB,CAAC;IAChH,YAAY,EAAE,4MAA4M;CAC3N,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAa;IACtC,IAAI,EAAE,eAAe;IACrB,IAAI,EAAE,wFAAwF;IAC9F,KAAK,EAAE,CAAC,mBAAmB,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,mBAAmB,CAAC;IACtH,YAAY,EAAE,8MAA8M;CAC7N,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAa;IACvC,IAAI,EAAE,gBAAgB;IACtB,IAAI,EAAE,iEAAiE;IACvE,KAAK,EAAE,CAAC,sBAAsB,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,8BAA8B,CAAC;IACrH,YAAY,EAAE,oMAAoM;CACnN,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAa;IACtC,IAAI,EAAE,eAAe;IACrB,IAAI,EAAE,qDAAqD;IAC3D,KAAK,EAAE,CAAC,eAAe,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,oBAAoB,CAAC;IAC9F,YAAY,EAAE,mJAAmJ;CAClK,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,CAAC,CAAC;AAE5F;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,IAAI,CAAC;AAClE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAmB;IACnD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAoB,CAAC;IAEhD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,SAAS,GAAG,KAAK,EAAE,IAAI,IAAI,gBAAgB,CAAC;QAClD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAChE,WAAW,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/D,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,cAAc;QAC9D,KAAK;KACN,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -207,6 +207,13 @@ export async function executeBenchmarkRun(user, scenario, sessionIndex, timeHori
|
|
|
207
207
|
result = await callTool("founder_local_weekly_reset", { daysBack: 7 });
|
|
208
208
|
break;
|
|
209
209
|
case "pre_delegation":
|
|
210
|
+
await callTool("founder_direction_assessment", {
|
|
211
|
+
query: prompt,
|
|
212
|
+
lens: user.role,
|
|
213
|
+
marketWorkflow: ["Claude Code", "MCP"],
|
|
214
|
+
});
|
|
215
|
+
result = await callTool("founder_local_synthesize", { packetType: scenario, daysBack: 7, query: prompt });
|
|
216
|
+
break;
|
|
210
217
|
case "important_change":
|
|
211
218
|
result = await callTool("founder_local_synthesize", { packetType: scenario, daysBack: 7 });
|
|
212
219
|
break;
|
|
@@ -216,6 +223,13 @@ export async function executeBenchmarkRun(user, scenario, sessionIndex, timeHori
|
|
|
216
223
|
if (findTool("run_recon")) {
|
|
217
224
|
await callTool("run_recon", { target: user.primaryEntity, focus: prompt });
|
|
218
225
|
}
|
|
226
|
+
if (scenario === "company_search" && user.role === "founder") {
|
|
227
|
+
await callTool("workflow_adoption_scan", {
|
|
228
|
+
query: prompt,
|
|
229
|
+
marketWorkflow: ["Claude Code", "MCP"],
|
|
230
|
+
installSurface: ["local", "dashboard"],
|
|
231
|
+
});
|
|
232
|
+
}
|
|
219
233
|
break;
|
|
220
234
|
default:
|
|
221
235
|
result = await callTool("founder_local_gather", { daysBack: 7 });
|