@inixiative/hivemind 0.1.7 → 0.1.8

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.
Files changed (73) hide show
  1. package/README.md +67 -6
  2. package/dist/agents/agents.test.js +79 -0
  3. package/dist/agents/getAgentByPid.d.ts +7 -0
  4. package/dist/agents/getAgentByPid.js +13 -0
  5. package/dist/agents/index.d.ts +4 -0
  6. package/dist/agents/index.js +4 -0
  7. package/dist/agents/livenessMode.d.ts +2 -0
  8. package/dist/agents/livenessMode.js +13 -0
  9. package/dist/agents/registerAgent.js +4 -3
  10. package/dist/agents/touchAgent.d.ts +5 -0
  11. package/dist/agents/touchAgent.js +13 -0
  12. package/dist/agents/types.d.ts +1 -0
  13. package/dist/agents/updateAgentSession.d.ts +6 -0
  14. package/dist/agents/updateAgentSession.js +12 -0
  15. package/dist/cli/init.js +13 -5
  16. package/dist/cli/install.d.ts +1 -0
  17. package/dist/cli/install.js +9 -5
  18. package/dist/cli/registerMcp.js +4 -3
  19. package/dist/coordinator/index.js +32 -0
  20. package/dist/db/db.test.js +4 -3
  21. package/dist/db/getConnection.js +2 -0
  22. package/dist/db/initializeDb.js +2 -0
  23. package/dist/db/migrateDb.d.ts +6 -0
  24. package/dist/db/migrateDb.js +14 -0
  25. package/dist/db/schema.sql +134 -0
  26. package/dist/git/getBranch.d.ts +1 -1
  27. package/dist/git/getBranch.js +2 -2
  28. package/dist/git/getCurrentWorktree.d.ts +2 -2
  29. package/dist/git/getCurrentWorktree.js +6 -6
  30. package/dist/git/getGitInfo.d.ts +2 -2
  31. package/dist/git/getGitInfo.js +6 -6
  32. package/dist/git/getRepoName.d.ts +1 -1
  33. package/dist/git/getRepoName.js +3 -3
  34. package/dist/git/getRepoRoot.d.ts +1 -1
  35. package/dist/git/getRepoRoot.js +2 -2
  36. package/dist/git/getWorktrees.d.ts +1 -1
  37. package/dist/git/getWorktrees.js +2 -2
  38. package/dist/git/isGitRepo.d.ts +2 -2
  39. package/dist/git/isGitRepo.js +3 -3
  40. package/dist/hooks/sessionStart.d.ts +1 -1
  41. package/dist/hooks/sessionStart.js +77 -13
  42. package/dist/init/claudeConfig.d.ts +13 -3
  43. package/dist/init/claudeConfig.js +71 -29
  44. package/dist/mcp/core.d.ts +157 -0
  45. package/dist/mcp/core.js +78 -0
  46. package/dist/mcp/httpServer.d.ts +5 -0
  47. package/dist/mcp/httpServer.js +142 -0
  48. package/dist/mcp/httpServer.test.d.ts +1 -0
  49. package/dist/mcp/httpServer.test.js +164 -0
  50. package/dist/mcp/server.js +2 -93
  51. package/dist/mcp/tools/emitEvent.d.ts +1 -0
  52. package/dist/mcp/tools/emitEvent.js +20 -5
  53. package/dist/mcp/tools/events.d.ts +10 -0
  54. package/dist/mcp/tools/events.js +13 -0
  55. package/dist/mcp/tools/query.d.ts +5 -0
  56. package/dist/mcp/tools/query.js +15 -0
  57. package/dist/mcp/tools/register.d.ts +1 -0
  58. package/dist/mcp/tools/register.js +46 -24
  59. package/dist/mcp/tools/status.d.ts +35 -4
  60. package/dist/mcp/tools/status.js +103 -13
  61. package/dist/mcp/tools/status.test.d.ts +1 -0
  62. package/dist/mcp/tools/status.test.js +93 -0
  63. package/dist/mcp/tools/tasks.js +4 -0
  64. package/dist/test/factories/index.d.ts +1 -0
  65. package/dist/test/factories/index.js +1 -0
  66. package/dist/test/factories/worktreeFactory.d.ts +11 -0
  67. package/dist/test/factories/worktreeFactory.js +15 -0
  68. package/dist/test/setup.d.ts +1 -1
  69. package/dist/test/setup.js +30 -28
  70. package/dist/watcher/planWatcher.js +18 -0
  71. package/dist/worktrees/syncWorktreesFromGit.d.ts +1 -1
  72. package/dist/worktrees/syncWorktreesFromGit.js +2 -2
  73. package/package.json +2 -1
@@ -1,7 +1,7 @@
1
1
  import { Database } from 'bun:sqlite';
2
2
  export type TestDb = {
3
3
  db: Database;
4
- path: string;
4
+ project: string;
5
5
  cleanup: () => void;
6
6
  clearAllTables: () => void;
7
7
  };
@@ -2,49 +2,51 @@ import { Database } from 'bun:sqlite';
2
2
  import { readFileSync } from 'fs';
3
3
  import { join, dirname } from 'path';
4
4
  import { fileURLToPath } from 'url';
5
- import { mkdirSync, rmSync, existsSync } from 'fs';
5
+ import { setConnection } from '../db/getConnection';
6
6
  const __dirname = dirname(fileURLToPath(import.meta.url));
7
- const TEST_DB_DIR = join(__dirname, '../../.test-db');
7
+ // Single shared in-memory database for all tests
8
+ let sharedDb = null;
8
9
  let testDbCounter = 0;
10
+ function getOrCreateSharedDb() {
11
+ if (!sharedDb) {
12
+ sharedDb = new Database(':memory:');
13
+ sharedDb.exec('PRAGMA foreign_keys = ON');
14
+ const schemaPath = join(__dirname, '../db/schema.sql');
15
+ const schema = readFileSync(schemaPath, 'utf-8');
16
+ sharedDb.exec(schema);
17
+ }
18
+ return sharedDb;
19
+ }
9
20
  export function createTestDb() {
10
21
  testDbCounter++;
11
- const dbPath = join(TEST_DB_DIR, `test-${Date.now()}-${testDbCounter}.sqlite`);
12
- if (!existsSync(TEST_DB_DIR)) {
13
- mkdirSync(TEST_DB_DIR, { recursive: true });
14
- }
15
- const db = new Database(dbPath);
16
- db.exec('PRAGMA journal_mode = WAL');
17
- db.exec('PRAGMA busy_timeout = 5000');
18
- db.exec('PRAGMA foreign_keys = ON');
19
- const schemaPath = join(__dirname, '../db/schema.sql');
20
- const schema = readFileSync(schemaPath, 'utf-8');
21
- db.exec(schema);
22
+ const project = `test-project-${Date.now()}-${testDbCounter}`;
23
+ const db = getOrCreateSharedDb();
24
+ // Register with connection cache so getConnection(project) works
25
+ setConnection(project, db);
22
26
  const clearAllTables = () => {
23
- // Order matters due to FK constraints - delete children first
27
+ // Disable FK checks for cleanup (circular refs between agents/plans/tasks)
28
+ db.exec('PRAGMA foreign_keys = OFF');
24
29
  db.exec('DELETE FROM events');
25
30
  db.exec('DELETE FROM tasks');
26
31
  db.exec('DELETE FROM plans');
27
32
  db.exec('DELETE FROM agents');
28
33
  db.exec('DELETE FROM worktrees');
29
- // Reset sequence counter
30
34
  db.exec("UPDATE sequences SET value = 0 WHERE name = 'events'");
35
+ db.exec('PRAGMA foreign_keys = ON');
31
36
  };
32
37
  const cleanup = () => {
33
- db.close();
34
- if (existsSync(dbPath)) {
35
- rmSync(dbPath, { force: true });
36
- }
37
- if (existsSync(`${dbPath}-wal`)) {
38
- rmSync(`${dbPath}-wal`, { force: true });
39
- }
40
- if (existsSync(`${dbPath}-shm`)) {
41
- rmSync(`${dbPath}-shm`, { force: true });
42
- }
38
+ // Clear tables for next test
39
+ clearAllTables();
40
+ // Remove this project from connection cache (but don't close the shared db)
41
+ // We need a way to just remove from cache without closing
42
+ // For now, we'll just clear tables - the project name is unique anyway
43
43
  };
44
- return { db, path: dbPath, cleanup, clearAllTables };
44
+ return { db, project, cleanup, clearAllTables };
45
45
  }
46
46
  export function cleanupAllTestDbs() {
47
- if (existsSync(TEST_DB_DIR)) {
48
- rmSync(TEST_DB_DIR, { recursive: true, force: true });
47
+ if (sharedDb) {
48
+ sharedDb.close();
49
+ sharedDb = null;
49
50
  }
51
+ testDbCounter = 0;
50
52
  }
@@ -31,6 +31,19 @@ function parsePlanTitle(content) {
31
31
  const match = content.match(/^#\s+(.+)$/m);
32
32
  return match ? match[1].trim() : null;
33
33
  }
34
+ /**
35
+ * Parse project from YAML frontmatter
36
+ * Looks for: ---\nproject: Name\n---
37
+ */
38
+ function parseProjectFromPlan(content) {
39
+ // Match YAML frontmatter block and extract project field
40
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
41
+ if (!frontmatterMatch)
42
+ return null;
43
+ const frontmatter = frontmatterMatch[1];
44
+ const projectMatch = frontmatter.match(/^project:\s*(.+?)\s*$/m);
45
+ return projectMatch ? projectMatch[1].trim() : null;
46
+ }
34
47
  /**
35
48
  * Sync a single plan file to hivemind
36
49
  * Uses LLM to extract tasks, then reconciles with DB
@@ -60,6 +73,11 @@ export async function syncPlanFile(project, filename) {
60
73
  }
61
74
  // Read and parse
62
75
  const content = readFileSync(filePath, 'utf-8');
76
+ // Check if plan belongs to a different project
77
+ const planProject = parseProjectFromPlan(content);
78
+ if (planProject && planProject !== project) {
79
+ return { success: false, message: `Skipping (belongs to ${planProject})` };
80
+ }
63
81
  const title = parsePlanTitle(content) || basename(filename, '.md');
64
82
  const db = getConnection(project);
65
83
  // Check if plan already exists
@@ -4,4 +4,4 @@ import type { WorktreeRecord } from './types';
4
4
  * Sync worktrees from git into the database
5
5
  * Returns list of all worktrees after sync
6
6
  */
7
- export declare function syncWorktreesFromGit(db: Database): WorktreeRecord[];
7
+ export declare function syncWorktreesFromGit(db: Database, cwd?: string): WorktreeRecord[];
@@ -8,8 +8,8 @@ import { emit } from '../events/emit';
8
8
  * Sync worktrees from git into the database
9
9
  * Returns list of all worktrees after sync
10
10
  */
11
- export function syncWorktreesFromGit(db) {
12
- const gitWorktrees = getGitWorktrees();
11
+ export function syncWorktreesFromGit(db, cwd) {
12
+ const gitWorktrees = getGitWorktrees(cwd);
13
13
  const results = [];
14
14
  for (const wt of gitWorktrees) {
15
15
  const existing = getWorktreeByPath(db, wt.path);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inixiative/hivemind",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Multi-agent coordination system for Claude Code - shared event log, plans, and tasks across multiple Claude sessions",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -43,6 +43,7 @@
43
43
  "dev": "tsc --watch",
44
44
  "test": "bun test src/",
45
45
  "mcp": "bun run src/mcp/server.ts",
46
+ "mcp:http": "bun run src/mcp/httpServer.ts",
46
47
  "cli": "bun run src/cli.ts"
47
48
  },
48
49
  "dependencies": {