hive-mind-agent 1.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/.cursor/mcp.json.example +11 -0
- package/.cursor/rules/hive-mind-central-brain.mdc +68 -0
- package/.cursor/settings.json +13 -0
- package/CONTRIBUTING.md +35 -0
- package/LICENSE +21 -0
- package/PUBLISH.md +62 -0
- package/README.md +98 -0
- package/api-server.mjs +159 -0
- package/cli.mjs +130 -0
- package/core/adapters/file-context-store.mjs +71 -0
- package/core/adapters/file-outcome-store.mjs +50 -0
- package/core/adapters/llm-provider.mjs +161 -0
- package/core/index.mjs +37 -0
- package/core/schema/config-schema.json +87 -0
- package/core/types.js +63 -0
- package/docs/agent-gaps-design.md +366 -0
- package/docs/api-server.md +42 -0
- package/docs/central-brain-interface.md +54 -0
- package/docs/config.md +61 -0
- package/docs/enterprise-agent-taxonomy.md +74 -0
- package/docs/graduation-path.md +53 -0
- package/docs/marketing-agent-suite-design.md +237 -0
- package/docs/mcp-server.md +36 -0
- package/docs/shared-state-format.md +71 -0
- package/docs/software-firmware-hardware-agent-design.md +364 -0
- package/docs/worker-contract.md +56 -0
- package/hive.config.example.json +21 -0
- package/mcp-server/index.mjs +148 -0
- package/package.json +41 -0
- package/scripts/install-skill.mjs +45 -0
- package/skill/CONTEXT_TEMPLATE.md +28 -0
- package/skill/SKILL.md +53 -0
- package/skill/reference.md +66 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Orchestrates multi-agent hive workflows. Project-agnostic; targets from hive.config.json.
|
|
3
|
+
globs: "**/*"
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Hive-Mind Central Brain
|
|
8
|
+
|
|
9
|
+
You are the central brain of a hive-mind. You set strategy, assign tasks to workers (subagents), ingest outcomes, and update shared context. Works with any project—targets and paths come from config.
|
|
10
|
+
|
|
11
|
+
## Config
|
|
12
|
+
|
|
13
|
+
If `hive.config.json` exists in the hive root, use it:
|
|
14
|
+
- `contextPath` (default `context.md`) — shared state file
|
|
15
|
+
- `outcomesPath` (default `outcomes`) — worker output directory
|
|
16
|
+
- `targetProducts` — products/projects to operate on; include in task context
|
|
17
|
+
- `maxParallelTasks` (default 3) — max parallel subagents per cycle
|
|
18
|
+
|
|
19
|
+
If no config exists, use `context.md` and `outcomes/` in the hive root.
|
|
20
|
+
|
|
21
|
+
## Loop
|
|
22
|
+
|
|
23
|
+
1. **Read** context (from config or `context.md`) — goals, strategy, pending tasks, recent outcomes, learnings
|
|
24
|
+
2. **Decide** 2–3 independent tasks that advance current goals
|
|
25
|
+
3. **Launch** 2–3 `mcp_task` subagents in parallel with clear task descriptions
|
|
26
|
+
4. **Collect** results when subagents complete
|
|
27
|
+
5. **Update** context — add outcome digest to Recent Outcomes, update Learnings, clear completed Pending Tasks
|
|
28
|
+
6. **Decide** next steps: more tasks, done, or human input
|
|
29
|
+
|
|
30
|
+
## Task Assignment
|
|
31
|
+
|
|
32
|
+
When invoking `mcp_task`, provide:
|
|
33
|
+
|
|
34
|
+
- **description** — 3–5 word summary (e.g. "Explore codebase for auth patterns")
|
|
35
|
+
- **prompt** — Full instructions including:
|
|
36
|
+
- What to do (concrete steps)
|
|
37
|
+
- Relevant context from context.md (goals, prior outcomes)
|
|
38
|
+
- Expected outcome (what to return or write)
|
|
39
|
+
- **subagent_type** — One of:
|
|
40
|
+
- **Base:** `explore` (codebase search), `shell` (commands), `generalPurpose` (research, complex tasks)
|
|
41
|
+
- **Builder:** `architect`, `implementer`, `reviewer`, `integrator`, `softwareSpecialist`, `firmwareSpecialist`, `hardwareSpecialist` — design, code, review, integrate, web/API/dashboard, embedded/BMS/IoT, PCB/electronics/enclosures
|
|
42
|
+
- **Operator:** `deployer`, `monitor`, `remediator`, `compliance` — release, observe, fix, assure controls
|
|
43
|
+
- **Grower:** `researcher`, `optimizer`, `experimenter`, `evangelist`, `launchSpecialist`, `fundraisingSpecialist`, `disruptorSpecialist`, `siteSelectionSpecialist`, `commissioningSpecialist`, `procurementSpecialist`, `permittingSpecialist` — research, optimize, experiment, adoption, GTM/launch, fundraising narrative, category creation, site due diligence, commissioning, procurement, permitting
|
|
44
|
+
|
|
45
|
+
Use `generalPurpose` + role in prompt for `launchSpecialist`, `fundraisingSpecialist`, `disruptorSpecialist` (MCP mcp_task has fixed enum).
|
|
46
|
+
|
|
47
|
+
See `docs/enterprise-agent-taxonomy.md` for full taxonomy and responsibilities.
|
|
48
|
+
|
|
49
|
+
Launch multiple subagents in one turn when tasks are independent.
|
|
50
|
+
|
|
51
|
+
## Outcome Ingestion
|
|
52
|
+
|
|
53
|
+
When subagents complete, read their responses and any files they wrote to `outcomes/`. Update `context.md`:
|
|
54
|
+
|
|
55
|
+
- Add row to Recent Outcomes (Date, Task, Status, Result)
|
|
56
|
+
- Add learnings to Learnings section if applicable
|
|
57
|
+
- Remove completed tasks from Pending Tasks
|
|
58
|
+
|
|
59
|
+
## Shared State
|
|
60
|
+
|
|
61
|
+
- **Context** (path from config or `context.md`) — You read and write this. Single source of truth.
|
|
62
|
+
- **Outcomes** (path from config or `outcomes/`) — Workers write here. You read to ingest.
|
|
63
|
+
|
|
64
|
+
Workers do not write to context. You aggregate their outcomes and update context.
|
|
65
|
+
|
|
66
|
+
## Taxonomy
|
|
67
|
+
|
|
68
|
+
See `docs/enterprise-agent-taxonomy.md` or custom `taxonomyPath` in config. MCP `mcp_task` has fixed enum; use `generalPurpose` + role in prompt for enterprise types.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Contributing to Hive-Mind Agent
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing. This project is open source and welcomes contributions from everyone.
|
|
4
|
+
|
|
5
|
+
## How to Contribute
|
|
6
|
+
|
|
7
|
+
### Reporting Issues
|
|
8
|
+
|
|
9
|
+
- Use GitHub Issues for bugs, feature requests, or questions
|
|
10
|
+
- Search existing issues first to avoid duplicates
|
|
11
|
+
- Include steps to reproduce for bugs
|
|
12
|
+
|
|
13
|
+
### Pull Requests
|
|
14
|
+
|
|
15
|
+
1. Fork the repository and create a branch (`git checkout -b feature/your-feature`)
|
|
16
|
+
2. Make your changes
|
|
17
|
+
3. Ensure the project runs: `npm install && node cli.mjs init` (in a temp dir)
|
|
18
|
+
4. Submit a PR with a clear description
|
|
19
|
+
|
|
20
|
+
### Areas We Need Help
|
|
21
|
+
|
|
22
|
+
- **Adapters:** Postgres/Redis context store, SQS task queue
|
|
23
|
+
- **LLM providers:** Additional providers (Gemini, Groq, etc.)
|
|
24
|
+
- **Documentation:** Examples, tutorials, non-English docs
|
|
25
|
+
- **Testing:** Unit tests, integration tests
|
|
26
|
+
|
|
27
|
+
### Code Style
|
|
28
|
+
|
|
29
|
+
- Use ES modules (`.mjs` or `"type": "module"`)
|
|
30
|
+
- No build step required—keep it runnable with plain Node
|
|
31
|
+
- Prefer minimal dependencies
|
|
32
|
+
|
|
33
|
+
### License
|
|
34
|
+
|
|
35
|
+
By contributing, you agree that your contributions will be licensed under the MIT License.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hive-Mind Agent Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/PUBLISH.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Publishing Hive-Mind Agent
|
|
2
|
+
|
|
3
|
+
Steps to publish as open source.
|
|
4
|
+
|
|
5
|
+
## 1. Create GitHub Repository
|
|
6
|
+
|
|
7
|
+
1. Go to [github.com/new](https://github.com/new)
|
|
8
|
+
2. Repository name: `hive-mind-agent`
|
|
9
|
+
3. Description: "Model-agnostic, project-agnostic multi-agent hive orchestration"
|
|
10
|
+
4. Public, add README (or skip if this repo has one)
|
|
11
|
+
5. Create repository
|
|
12
|
+
|
|
13
|
+
## 2. Push to GitHub
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cd /path/to/hive-mind-agent
|
|
17
|
+
git add .
|
|
18
|
+
git commit -m "Initial release: hive-mind orchestration for Cursor, CLI, MCP, API"
|
|
19
|
+
git branch -M main
|
|
20
|
+
git remote add origin https://github.com/log-wade/hive-mind-agent.git
|
|
21
|
+
git push -u origin main
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Update `package.json` `repository`, `bugs`, and `homepage` URLs if you use a different org.
|
|
25
|
+
|
|
26
|
+
## 3. Publish to npm
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Log in (one-time)
|
|
30
|
+
npm login
|
|
31
|
+
|
|
32
|
+
# Dry run to verify package contents
|
|
33
|
+
npm pack --dry-run
|
|
34
|
+
|
|
35
|
+
# Publish
|
|
36
|
+
npm publish
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
After publish, anyone can run:
|
|
40
|
+
```bash
|
|
41
|
+
npx hive-mind-agent init
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 4. Install Skill (for users)
|
|
45
|
+
|
|
46
|
+
Users who clone or install the package can install the Cursor skill:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
cd hive-mind-agent
|
|
50
|
+
npm run skill:install
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
This copies the skill to `~/.cursor/skills/hive-mind-orchestrator/`.
|
|
54
|
+
|
|
55
|
+
## 5. Release Tags
|
|
56
|
+
|
|
57
|
+
For versioned releases:
|
|
58
|
+
```bash
|
|
59
|
+
npm version patch # or minor, major
|
|
60
|
+
git push && git push --tags
|
|
61
|
+
npm publish
|
|
62
|
+
```
|
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Hive-Mind Agent
|
|
2
|
+
|
|
3
|
+
**Model-agnostic, project-agnostic, platform-agnostic** multi-agent orchestration. A central brain + subagent hive that works in Cursor, CLI, MCP, or API. Open source (MIT).
|
|
4
|
+
|
|
5
|
+
## How It Works
|
|
6
|
+
|
|
7
|
+
- **Central brain** — Sets strategy, assigns tasks, ingests outcomes, updates shared context
|
|
8
|
+
- **Workers** — Subagents (via `mcp_task` in Cursor, or local/HTTP adapters) execute tasks
|
|
9
|
+
- **Shared state** — `context.md` + `outcomes/` (paths configurable via `hive.config.json`)
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Run without installing (npx)
|
|
17
|
+
npx hive-mind-agent init
|
|
18
|
+
|
|
19
|
+
# Or clone and use locally
|
|
20
|
+
git clone https://github.com/hive-mind-agent/hive-mind-agent.git
|
|
21
|
+
cd hive-mind-agent && npm install
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Bootstrap a New Hive
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
cd your-project
|
|
28
|
+
npx hive-mind-agent init
|
|
29
|
+
# Edit hive.config.json and context.md
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Cursor
|
|
33
|
+
|
|
34
|
+
1. Open your project (with `hive.config.json` or `context.md`)
|
|
35
|
+
2. Add the **hive-mind-central-brain** rule (copy from this repo) or **hive-mind-orchestrator** Skill
|
|
36
|
+
3. Say: "Advance the hive" or "Unleash the hive"
|
|
37
|
+
|
|
38
|
+
### CLI
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
hive init # Bootstrap (or: npx hive-mind-agent init)
|
|
42
|
+
hive advance # Inspect context
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### MCP Server
|
|
46
|
+
|
|
47
|
+
Add to Cursor MCP config (see [docs/mcp-server.md](docs/mcp-server.md)):
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"mcpServers": {
|
|
52
|
+
"hive-mind": {
|
|
53
|
+
"command": "node",
|
|
54
|
+
"args": ["/path/to/hive-mind-agent/mcp-server/index.mjs"],
|
|
55
|
+
"env": { "HIVE_ROOT": "/path/to/your-hive" }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### API Server
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
HIVE_ROOT=/path/to/hive node api-server.mjs
|
|
65
|
+
# Or: npm run api
|
|
66
|
+
# Endpoints: GET/PUT /api/hive/context, GET /api/hive/config, POST /api/hive/cycle
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Structure
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
hive-mind-agent/
|
|
73
|
+
├── hive.config.json # Config (targets, adapters, paths)
|
|
74
|
+
├── context.md # Shared state
|
|
75
|
+
├── outcomes/ # Worker outputs
|
|
76
|
+
├── core/ # Adapters (context, outcome, LLM)
|
|
77
|
+
├── cli.mjs # CLI
|
|
78
|
+
├── mcp-server/ # MCP tools
|
|
79
|
+
├── api-server.mjs # HTTP API
|
|
80
|
+
├── docs/
|
|
81
|
+
└── .cursor/rules/ # Central brain rule
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Docs
|
|
85
|
+
|
|
86
|
+
- [Config](docs/config.md) — hive.config.json, adapters
|
|
87
|
+
- [MCP Server](docs/mcp-server.md) — Cursor MCP setup
|
|
88
|
+
- [API Server](docs/api-server.md) — HTTP API
|
|
89
|
+
- [Worker Contract](docs/worker-contract.md) — Task/outcome format
|
|
90
|
+
- [Graduation Path](docs/graduation-path.md) — Standalone scaling
|
|
91
|
+
|
|
92
|
+
## Contributing
|
|
93
|
+
|
|
94
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). Contributions welcome.
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
MIT — see [LICENSE](LICENSE).
|
package/api-server.mjs
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Hive API server. Exposes context and cycle endpoints.
|
|
4
|
+
* Run: HIVE_ROOT=/path/to/hive node api-server.mjs
|
|
5
|
+
* Endpoints:
|
|
6
|
+
* GET /api/hive/context - Read context
|
|
7
|
+
* PUT /api/hive/context - Update context (body: raw markdown)
|
|
8
|
+
* GET /api/hive/config - Get config
|
|
9
|
+
* GET /api/hive/outcomes - List outcomes
|
|
10
|
+
* POST /api/hive/cycle - Run one cycle (requires LLM; in Cursor mode returns instructions)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { createServer } from 'http';
|
|
14
|
+
import { loadConfig, readContext, writeContext, listOutcomes, createLLMProvider } from './core/index.mjs';
|
|
15
|
+
import { resolve } from 'path';
|
|
16
|
+
|
|
17
|
+
const HIVE_ROOT = process.env.HIVE_ROOT || process.cwd();
|
|
18
|
+
const PORT = parseInt(process.env.PORT || '3742', 10);
|
|
19
|
+
|
|
20
|
+
async function getContextPath() {
|
|
21
|
+
const config = await loadConfig(HIVE_ROOT);
|
|
22
|
+
return config?.contextPath ?? 'context.md';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function getOutcomesPath() {
|
|
26
|
+
const config = await loadConfig(HIVE_ROOT);
|
|
27
|
+
return config?.outcomesPath ?? 'outcomes';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function readRawContext() {
|
|
31
|
+
const { readFile } = await import('fs/promises');
|
|
32
|
+
const { join } = await import('path');
|
|
33
|
+
const contextPath = await getContextPath();
|
|
34
|
+
const path = join(HIVE_ROOT, contextPath);
|
|
35
|
+
return readFile(path, 'utf-8');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function writeRawContext(content) {
|
|
39
|
+
const { writeFile } = await import('fs/promises');
|
|
40
|
+
const { join } = await import('path');
|
|
41
|
+
const contextPath = await getContextPath();
|
|
42
|
+
const path = join(HIVE_ROOT, contextPath);
|
|
43
|
+
await writeFile(path, content);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function handleGetContext(res) {
|
|
47
|
+
try {
|
|
48
|
+
const content = await readRawContext();
|
|
49
|
+
res.writeHead(200, { 'Content-Type': 'text/markdown' });
|
|
50
|
+
res.end(content);
|
|
51
|
+
} catch (err) {
|
|
52
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
53
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function handlePutContext(req, res) {
|
|
58
|
+
let body = '';
|
|
59
|
+
for await (const chunk of req) body += chunk;
|
|
60
|
+
try {
|
|
61
|
+
await writeRawContext(body);
|
|
62
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
63
|
+
res.end(JSON.stringify({ ok: true }));
|
|
64
|
+
} catch (err) {
|
|
65
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
66
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function handleGetConfig(res) {
|
|
71
|
+
try {
|
|
72
|
+
const config = await loadConfig(HIVE_ROOT);
|
|
73
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
74
|
+
res.end(JSON.stringify(config || {}));
|
|
75
|
+
} catch (err) {
|
|
76
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
77
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function handleGetOutcomes(res) {
|
|
82
|
+
try {
|
|
83
|
+
const outcomesPath = await getOutcomesPath();
|
|
84
|
+
const outcomes = await listOutcomes(HIVE_ROOT, outcomesPath);
|
|
85
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
86
|
+
res.end(JSON.stringify(outcomes));
|
|
87
|
+
} catch (err) {
|
|
88
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
89
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function handlePostCycle(res) {
|
|
94
|
+
const config = await loadConfig(HIVE_ROOT);
|
|
95
|
+
const llmConfig = config?.adapters?.llm;
|
|
96
|
+
const llm = createLLMProvider(llmConfig);
|
|
97
|
+
|
|
98
|
+
if (llmConfig?.type === 'cursor' || !llmConfig?.type) {
|
|
99
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
100
|
+
res.end(
|
|
101
|
+
JSON.stringify({
|
|
102
|
+
message:
|
|
103
|
+
'Cursor mode: run cycle in Cursor. Say "Advance the hive" or "Unleash the hive" to orchestrate.',
|
|
104
|
+
hint: 'Set adapters.llm.type to anthropic, openai, or ollama for headless cycles.',
|
|
105
|
+
})
|
|
106
|
+
);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const contextPath = await getContextPath();
|
|
112
|
+
const parsed = await readContext(HIVE_ROOT, contextPath);
|
|
113
|
+
const systemPrompt = `You are the central brain of a hive-mind. Given the context, decide 2-3 independent tasks.
|
|
114
|
+
Return JSON: { "tasks": [ { "description": "...", "prompt": "...", "subagentType": "explore|shell|generalPurpose" } ] }
|
|
115
|
+
Only return valid JSON, no markdown.`;
|
|
116
|
+
const prompt = `Context:\nGoals: ${JSON.stringify(parsed.goals)}\nStrategy: ${parsed.strategy}\nPending: ${parsed.pendingTasks}\n\nDecide tasks.`;
|
|
117
|
+
const out = await llm.complete({ prompt, systemPrompt });
|
|
118
|
+
const json = JSON.parse(out.replace(/```json?\n?|\n?```/g, '').trim());
|
|
119
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
120
|
+
res.end(
|
|
121
|
+
JSON.stringify({
|
|
122
|
+
ok: true,
|
|
123
|
+
tasks: json.tasks || [],
|
|
124
|
+
message: 'Tasks decided. Worker execution not implemented in API; use Cursor or MCP.',
|
|
125
|
+
})
|
|
126
|
+
);
|
|
127
|
+
} catch (err) {
|
|
128
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
129
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const server = createServer(async (req, res) => {
|
|
134
|
+
const url = new URL(req.url || '/', `http://${req.headers.host}`);
|
|
135
|
+
const path = url.pathname;
|
|
136
|
+
const method = req.method;
|
|
137
|
+
|
|
138
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
139
|
+
if (method === 'OPTIONS') {
|
|
140
|
+
res.writeHead(204);
|
|
141
|
+
res.end();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (path === '/api/hive/context' && method === 'GET') return handleGetContext(res);
|
|
146
|
+
if (path === '/api/hive/context' && method === 'PUT') return handlePutContext(req, res);
|
|
147
|
+
if (path === '/api/hive/config' && method === 'GET') return handleGetConfig(res);
|
|
148
|
+
if (path === '/api/hive/outcomes' && method === 'GET') return handleGetOutcomes(res);
|
|
149
|
+
if (path === '/api/hive/cycle' && method === 'POST') return handlePostCycle(res);
|
|
150
|
+
|
|
151
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
152
|
+
res.end(JSON.stringify({ error: 'Not found' }));
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
server.listen(PORT, () => {
|
|
156
|
+
console.log(`Hive API server on http://localhost:${PORT}`);
|
|
157
|
+
console.log(`HIVE_ROOT: ${HIVE_ROOT}`);
|
|
158
|
+
console.log('Endpoints: GET/PUT /api/hive/context, GET /api/hive/config, GET /api/hive/outcomes, POST /api/hive/cycle');
|
|
159
|
+
});
|
package/cli.mjs
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Hive CLI. Bootstrap and run hive cycles.
|
|
4
|
+
* Usage: node cli.mjs init | advance [--cycles N]
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { mkdir, writeFile, readFile } from 'fs/promises';
|
|
8
|
+
import { join, dirname } from 'path';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
import { loadConfig, readContext, writeContext, listOutcomes } from './core/index.mjs';
|
|
11
|
+
|
|
12
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
|
|
14
|
+
const CONTEXT_TEMPLATE = `# Hive Context
|
|
15
|
+
|
|
16
|
+
## Goals
|
|
17
|
+
|
|
18
|
+
- **Primary:** [Describe the main objective]
|
|
19
|
+
- **Target product:** [Product name and path]
|
|
20
|
+
|
|
21
|
+
## Strategy
|
|
22
|
+
|
|
23
|
+
[Current approach]
|
|
24
|
+
|
|
25
|
+
## Pending Tasks
|
|
26
|
+
|
|
27
|
+
| ID | Description | Assigned | Status |
|
|
28
|
+
|----|-------------|----------|--------|
|
|
29
|
+
| 1 | [Task] | - | pending |
|
|
30
|
+
|
|
31
|
+
## Recent Outcomes (last 10)
|
|
32
|
+
|
|
33
|
+
| Date | Task | Status | Result |
|
|
34
|
+
|------|------|--------|--------|
|
|
35
|
+
| | | | |
|
|
36
|
+
|
|
37
|
+
## Learnings
|
|
38
|
+
|
|
39
|
+
-
|
|
40
|
+
`;
|
|
41
|
+
|
|
42
|
+
const CONFIG_TEMPLATE = {
|
|
43
|
+
version: 1,
|
|
44
|
+
targetProducts: [],
|
|
45
|
+
workspaceRoots: [],
|
|
46
|
+
adapters: {
|
|
47
|
+
context: { type: 'file', options: {} },
|
|
48
|
+
outcome: { type: 'file', options: {} },
|
|
49
|
+
worker: { type: 'cursor', options: {} },
|
|
50
|
+
llm: { type: 'cursor', options: {} },
|
|
51
|
+
},
|
|
52
|
+
maxParallelTasks: 3,
|
|
53
|
+
contextPath: 'context.md',
|
|
54
|
+
outcomesPath: 'outcomes',
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
async function init(cwd = process.cwd()) {
|
|
58
|
+
const configPath = join(cwd, 'hive.config.json');
|
|
59
|
+
const contextPath = join(cwd, 'context.md');
|
|
60
|
+
const outcomesDir = join(cwd, 'outcomes');
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
await readFile(configPath);
|
|
64
|
+
console.log('hive.config.json already exists');
|
|
65
|
+
} catch {
|
|
66
|
+
await writeFile(configPath, JSON.stringify(CONFIG_TEMPLATE, null, 2));
|
|
67
|
+
console.log('Created hive.config.json');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
await readFile(contextPath);
|
|
72
|
+
console.log('context.md already exists');
|
|
73
|
+
} catch {
|
|
74
|
+
await writeFile(contextPath, CONTEXT_TEMPLATE);
|
|
75
|
+
console.log('Created context.md');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
await mkdir(outcomesDir, { recursive: true });
|
|
79
|
+
console.log('Ensured outcomes/ directory');
|
|
80
|
+
|
|
81
|
+
console.log('\nHive initialized. Edit hive.config.json and context.md, then run: hive advance');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function advance(cwd = process.cwd(), cycles = 1) {
|
|
85
|
+
const config = await loadConfig(cwd);
|
|
86
|
+
const contextPath = config?.contextPath ?? 'context.md';
|
|
87
|
+
const outcomesPath = config?.outcomesPath ?? 'outcomes';
|
|
88
|
+
|
|
89
|
+
console.log('Hive advance (Cursor mode)');
|
|
90
|
+
console.log('---');
|
|
91
|
+
console.log('When running via CLI, the central brain logic runs in Cursor.');
|
|
92
|
+
console.log('This CLI is for bootstrapping and file inspection.\n');
|
|
93
|
+
|
|
94
|
+
const parsed = await readContext(cwd, contextPath);
|
|
95
|
+
console.log('Context summary:');
|
|
96
|
+
console.log(' Goals:', parsed.goals?.length ?? 0);
|
|
97
|
+
console.log(' Strategy:', parsed.strategy ? parsed.strategy.slice(0, 80) + '...' : '(empty)');
|
|
98
|
+
console.log(' Pending tasks: see context.md');
|
|
99
|
+
|
|
100
|
+
const outcomes = await listOutcomes(cwd, outcomesPath);
|
|
101
|
+
console.log(' Recent outcomes:', outcomes.length);
|
|
102
|
+
|
|
103
|
+
console.log('\nTo run a cycle: open this project in Cursor, enable the hive-mind-central-brain rule, and say "Advance the hive" or "Unleash the hive".');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const cmd = process.argv[2] ?? 'help';
|
|
107
|
+
const cycles = parseInt(process.argv.find((a) => a.startsWith('--cycles='))?.split('=')[1] ?? '1', 10);
|
|
108
|
+
const cwd = process.cwd();
|
|
109
|
+
|
|
110
|
+
if (cmd === 'init') {
|
|
111
|
+
init(cwd).catch((e) => {
|
|
112
|
+
console.error(e);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
});
|
|
115
|
+
} else if (cmd === 'advance') {
|
|
116
|
+
advance(cwd, cycles).catch((e) => {
|
|
117
|
+
console.error(e);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
});
|
|
120
|
+
} else {
|
|
121
|
+
console.log(`
|
|
122
|
+
Hive CLI — Multi-agent orchestration
|
|
123
|
+
|
|
124
|
+
Usage:
|
|
125
|
+
node cli.mjs init Bootstrap hive in current directory
|
|
126
|
+
node cli.mjs advance Inspect context (full cycle runs in Cursor)
|
|
127
|
+
|
|
128
|
+
Or: npm run hive:init | hive:advance
|
|
129
|
+
`);
|
|
130
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-based context store. Reads/writes context.md.
|
|
3
|
+
* @module hive-core/adapters/file-context-store
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { readFile, writeFile } from 'fs/promises';
|
|
7
|
+
import { dirname, join } from 'path';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
|
|
10
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Parse context.md into structured object (simplified; full parse is markdown).
|
|
14
|
+
* @param {string} content
|
|
15
|
+
* @returns {{ goals: string[], strategy: string, pendingTasks: string[], recentOutcomes: string[], learnings: string[] }}
|
|
16
|
+
*/
|
|
17
|
+
function parseContext(content) {
|
|
18
|
+
const sections = {};
|
|
19
|
+
let current = null;
|
|
20
|
+
let buffer = [];
|
|
21
|
+
|
|
22
|
+
for (const line of content.split('\n')) {
|
|
23
|
+
if (line.startsWith('## ')) {
|
|
24
|
+
if (current) sections[current] = buffer.join('\n').trim();
|
|
25
|
+
current = line.slice(3).trim();
|
|
26
|
+
buffer = [];
|
|
27
|
+
} else {
|
|
28
|
+
buffer.push(line);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (current) sections[current] = buffer.join('\n').trim();
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
raw: content,
|
|
35
|
+
goals: parseList(sections['Goals'] || sections[' goals'] || ''),
|
|
36
|
+
strategy: sections['Strategy'] || sections[' strategy'] || '',
|
|
37
|
+
pendingTasks: sections['Pending Tasks'] || sections[' pending tasks'] || '',
|
|
38
|
+
recentOutcomes: sections['Recent Outcomes (last 10)'] || sections['Recent Outcomes'] || '',
|
|
39
|
+
learnings: parseList(sections['Learnings'] || sections[' learnings'] || ''),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function parseList(text) {
|
|
44
|
+
return text
|
|
45
|
+
.split('\n')
|
|
46
|
+
.map((s) => s.replace(/^[-*]\s*/, '').trim())
|
|
47
|
+
.filter(Boolean);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {string} rootDir
|
|
52
|
+
* @param {string} [contextPath='context.md']
|
|
53
|
+
* @returns {Promise<{ raw: string, goals: string[], strategy: string, pendingTasks: string, recentOutcomes: string, learnings: string[] }>}
|
|
54
|
+
*/
|
|
55
|
+
export async function readContext(rootDir, contextPath = 'context.md') {
|
|
56
|
+
const path = join(rootDir, contextPath);
|
|
57
|
+
const content = await readFile(path, 'utf-8');
|
|
58
|
+
return parseContext(content);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param {string} rootDir
|
|
63
|
+
* @param {string} content
|
|
64
|
+
* @param {string} [contextPath='context.md']
|
|
65
|
+
*/
|
|
66
|
+
export async function writeContext(rootDir, content, contextPath = 'context.md') {
|
|
67
|
+
const path = join(rootDir, contextPath);
|
|
68
|
+
await writeFile(path, content);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { parseContext };
|