@inixiative/hivemind 0.1.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.
Files changed (287) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -0
  3. package/dist/agents/agents.test.d.ts +1 -0
  4. package/dist/agents/agents.test.js +167 -0
  5. package/dist/agents/getActiveAgents.d.ts +6 -0
  6. package/dist/agents/getActiveAgents.js +11 -0
  7. package/dist/agents/getAgent.d.ts +6 -0
  8. package/dist/agents/getAgent.js +7 -0
  9. package/dist/agents/getAgentBySessionId.d.ts +10 -0
  10. package/dist/agents/getAgentBySessionId.js +17 -0
  11. package/dist/agents/index.d.ts +10 -0
  12. package/dist/agents/index.js +12 -0
  13. package/dist/agents/markAgentDead.d.ts +6 -0
  14. package/dist/agents/markAgentDead.js +26 -0
  15. package/dist/agents/markAgentIdle.d.ts +5 -0
  16. package/dist/agents/markAgentIdle.js +12 -0
  17. package/dist/agents/registerAgent.d.ts +6 -0
  18. package/dist/agents/registerAgent.js +29 -0
  19. package/dist/agents/types.d.ts +30 -0
  20. package/dist/agents/types.js +1 -0
  21. package/dist/agents/unregisterAgent.d.ts +5 -0
  22. package/dist/agents/unregisterAgent.js +8 -0
  23. package/dist/agents/updateAgentContext.d.ts +5 -0
  24. package/dist/agents/updateAgentContext.js +12 -0
  25. package/dist/agents/updateAgentTask.d.ts +5 -0
  26. package/dist/agents/updateAgentTask.js +12 -0
  27. package/dist/agents/updateAgentWorktree.d.ts +5 -0
  28. package/dist/agents/updateAgentWorktree.js +12 -0
  29. package/dist/cli/index.d.ts +8 -0
  30. package/dist/cli/index.js +8 -0
  31. package/dist/cli/init.d.ts +14 -0
  32. package/dist/cli/init.js +71 -0
  33. package/dist/cli/install.d.ts +8 -0
  34. package/dist/cli/install.js +47 -0
  35. package/dist/cli/join.d.ts +9 -0
  36. package/dist/cli/join.js +38 -0
  37. package/dist/cli/registerMcp.d.ts +28 -0
  38. package/dist/cli/registerMcp.js +138 -0
  39. package/dist/cli/status.d.ts +8 -0
  40. package/dist/cli/status.js +82 -0
  41. package/dist/cli/watch.d.ts +6 -0
  42. package/dist/cli/watch.js +68 -0
  43. package/dist/cli.d.ts +12 -0
  44. package/dist/cli.js +49 -0
  45. package/dist/coordinator/coordinator.test.d.ts +1 -0
  46. package/dist/coordinator/coordinator.test.js +171 -0
  47. package/dist/coordinator/index.d.ts +16 -0
  48. package/dist/coordinator/index.js +166 -0
  49. package/dist/coordinator/spawn.d.ts +22 -0
  50. package/dist/coordinator/spawn.js +66 -0
  51. package/dist/datetime/datetime.test.d.ts +1 -0
  52. package/dist/datetime/datetime.test.js +63 -0
  53. package/dist/datetime/formatDate.d.ts +6 -0
  54. package/dist/datetime/formatDate.js +11 -0
  55. package/dist/datetime/formatDatetime.d.ts +6 -0
  56. package/dist/datetime/formatDatetime.js +12 -0
  57. package/dist/datetime/formatTime.d.ts +6 -0
  58. package/dist/datetime/formatTime.js +11 -0
  59. package/dist/datetime/index.d.ts +4 -0
  60. package/dist/datetime/index.js +7 -0
  61. package/dist/datetime/isStale.d.ts +10 -0
  62. package/dist/datetime/isStale.js +18 -0
  63. package/dist/datetime/now.d.ts +6 -0
  64. package/dist/datetime/now.js +9 -0
  65. package/dist/datetime/parseDatetime.d.ts +7 -0
  66. package/dist/datetime/parseDatetime.js +28 -0
  67. package/dist/db/constants.d.ts +4 -0
  68. package/dist/db/constants.js +6 -0
  69. package/dist/db/db.test.d.ts +1 -0
  70. package/dist/db/db.test.js +141 -0
  71. package/dist/db/ensureProjectDirs.d.ts +4 -0
  72. package/dist/db/ensureProjectDirs.js +12 -0
  73. package/dist/db/getConnection.d.ts +19 -0
  74. package/dist/db/getConnection.js +51 -0
  75. package/dist/db/getCurrentProject.d.ts +8 -0
  76. package/dist/db/getCurrentProject.js +14 -0
  77. package/dist/db/getProjectPaths.d.ts +21 -0
  78. package/dist/db/getProjectPaths.js +26 -0
  79. package/dist/db/index.d.ts +10 -0
  80. package/dist/db/index.js +13 -0
  81. package/dist/db/initializeDb.d.ts +7 -0
  82. package/dist/db/initializeDb.js +23 -0
  83. package/dist/db/nextEventSeq.d.ts +5 -0
  84. package/dist/db/nextEventSeq.js +13 -0
  85. package/dist/db/nextSubtaskSeq.d.ts +5 -0
  86. package/dist/db/nextSubtaskSeq.js +12 -0
  87. package/dist/db/nextTaskSeq.d.ts +5 -0
  88. package/dist/db/nextTaskSeq.js +13 -0
  89. package/dist/db/resetDb.d.ts +10 -0
  90. package/dist/db/resetDb.js +36 -0
  91. package/dist/events/emit.d.ts +6 -0
  92. package/dist/events/emit.js +31 -0
  93. package/dist/events/events.test.d.ts +1 -0
  94. package/dist/events/events.test.js +145 -0
  95. package/dist/events/getEventsByAgent.d.ts +6 -0
  96. package/dist/events/getEventsByAgent.js +14 -0
  97. package/dist/events/getEventsByBranch.d.ts +6 -0
  98. package/dist/events/getEventsByBranch.js +12 -0
  99. package/dist/events/getEventsByPlan.d.ts +6 -0
  100. package/dist/events/getEventsByPlan.js +14 -0
  101. package/dist/events/getEventsByWorktree.d.ts +6 -0
  102. package/dist/events/getEventsByWorktree.js +12 -0
  103. package/dist/events/getEventsSince.d.ts +12 -0
  104. package/dist/events/getEventsSince.js +47 -0
  105. package/dist/events/getRecentEvents.d.ts +6 -0
  106. package/dist/events/getRecentEvents.js +12 -0
  107. package/dist/events/index.d.ts +8 -0
  108. package/dist/events/index.js +9 -0
  109. package/dist/events/types.d.ts +34 -0
  110. package/dist/events/types.js +1 -0
  111. package/dist/git/getBranch.d.ts +4 -0
  112. package/dist/git/getBranch.js +14 -0
  113. package/dist/git/getCurrentWorktree.d.ts +5 -0
  114. package/dist/git/getCurrentWorktree.js +15 -0
  115. package/dist/git/getGitInfo.d.ts +10 -0
  116. package/dist/git/getGitInfo.js +23 -0
  117. package/dist/git/getRepoName.d.ts +4 -0
  118. package/dist/git/getRepoName.js +32 -0
  119. package/dist/git/getRepoRoot.d.ts +4 -0
  120. package/dist/git/getRepoRoot.js +14 -0
  121. package/dist/git/getWorktrees.d.ts +10 -0
  122. package/dist/git/getWorktrees.js +39 -0
  123. package/dist/git/index.d.ts +9 -0
  124. package/dist/git/index.js +7 -0
  125. package/dist/git/isGitRepo.d.ts +4 -0
  126. package/dist/git/isGitRepo.js +13 -0
  127. package/dist/hooks/index.d.ts +1 -0
  128. package/dist/hooks/index.js +1 -0
  129. package/dist/hooks/sessionStart.d.ts +21 -0
  130. package/dist/hooks/sessionStart.js +93 -0
  131. package/dist/ids/generateHex.d.ts +4 -0
  132. package/dist/ids/generateHex.js +7 -0
  133. package/dist/ids/getParentTaskId.d.ts +7 -0
  134. package/dist/ids/getParentTaskId.js +15 -0
  135. package/dist/ids/getPlanHexFromTaskId.d.ts +6 -0
  136. package/dist/ids/getPlanHexFromTaskId.js +9 -0
  137. package/dist/ids/ids.test.d.ts +1 -0
  138. package/dist/ids/ids.test.js +215 -0
  139. package/dist/ids/index.d.ts +16 -0
  140. package/dist/ids/index.js +17 -0
  141. package/dist/ids/isSubtask.d.ts +7 -0
  142. package/dist/ids/isSubtask.js +11 -0
  143. package/dist/ids/isValidId.d.ts +9 -0
  144. package/dist/ids/isValidId.js +22 -0
  145. package/dist/ids/makeAgentId.d.ts +8 -0
  146. package/dist/ids/makeAgentId.js +15 -0
  147. package/dist/ids/makeEventId.d.ts +11 -0
  148. package/dist/ids/makeEventId.js +12 -0
  149. package/dist/ids/makePlanId.d.ts +11 -0
  150. package/dist/ids/makePlanId.js +15 -0
  151. package/dist/ids/makeSubtaskId.d.ts +8 -0
  152. package/dist/ids/makeSubtaskId.js +15 -0
  153. package/dist/ids/makeTaskId.d.ts +8 -0
  154. package/dist/ids/makeTaskId.js +14 -0
  155. package/dist/ids/makeWorktreeId.d.ts +5 -0
  156. package/dist/ids/makeWorktreeId.js +12 -0
  157. package/dist/ids/parseId.d.ts +11 -0
  158. package/dist/ids/parseId.js +26 -0
  159. package/dist/ids/sanitizeLabel.d.ts +7 -0
  160. package/dist/ids/sanitizeLabel.js +12 -0
  161. package/dist/ids/typedIds.d.ts +34 -0
  162. package/dist/ids/typedIds.js +22 -0
  163. package/dist/ids/types.d.ts +14 -0
  164. package/dist/ids/types.js +1 -0
  165. package/dist/init/claudeConfig.d.ts +39 -0
  166. package/dist/init/claudeConfig.js +161 -0
  167. package/dist/llm/extractTasks.d.ts +28 -0
  168. package/dist/llm/extractTasks.js +108 -0
  169. package/dist/llm/index.d.ts +2 -0
  170. package/dist/llm/index.js +2 -0
  171. package/dist/llm/reconcileTasks.d.ts +21 -0
  172. package/dist/llm/reconcileTasks.js +82 -0
  173. package/dist/mcp/server.d.ts +2 -0
  174. package/dist/mcp/server.js +100 -0
  175. package/dist/mcp/tools/emitEvent.d.ts +62 -0
  176. package/dist/mcp/tools/emitEvent.js +84 -0
  177. package/dist/mcp/tools/events.d.ts +55 -0
  178. package/dist/mcp/tools/events.js +56 -0
  179. package/dist/mcp/tools/index.d.ts +18 -0
  180. package/dist/mcp/tools/index.js +13 -0
  181. package/dist/mcp/tools/query.d.ts +54 -0
  182. package/dist/mcp/tools/query.js +70 -0
  183. package/dist/mcp/tools/register.d.ts +47 -0
  184. package/dist/mcp/tools/register.js +79 -0
  185. package/dist/mcp/tools/reset.d.ts +38 -0
  186. package/dist/mcp/tools/reset.js +56 -0
  187. package/dist/mcp/tools/setup.d.ts +42 -0
  188. package/dist/mcp/tools/setup.js +75 -0
  189. package/dist/mcp/tools/status.d.ts +44 -0
  190. package/dist/mcp/tools/status.js +74 -0
  191. package/dist/mcp/tools/tasks.d.ts +116 -0
  192. package/dist/mcp/tools/tasks.js +143 -0
  193. package/dist/mcp/tools/worktreeCleanup.d.ts +38 -0
  194. package/dist/mcp/tools/worktreeCleanup.js +67 -0
  195. package/dist/plans/createPlan.d.ts +6 -0
  196. package/dist/plans/createPlan.js +29 -0
  197. package/dist/plans/getActivePlans.d.ts +6 -0
  198. package/dist/plans/getActivePlans.js +11 -0
  199. package/dist/plans/getPlan.d.ts +6 -0
  200. package/dist/plans/getPlan.js +7 -0
  201. package/dist/plans/index.d.ts +5 -0
  202. package/dist/plans/index.js +5 -0
  203. package/dist/plans/plans.test.d.ts +1 -0
  204. package/dist/plans/plans.test.js +107 -0
  205. package/dist/plans/types.d.ts +32 -0
  206. package/dist/plans/types.js +1 -0
  207. package/dist/plans/updatePlanStatus.d.ts +6 -0
  208. package/dist/plans/updatePlanStatus.js +8 -0
  209. package/dist/tasks/assignTask.d.ts +7 -0
  210. package/dist/tasks/assignTask.js +20 -0
  211. package/dist/tasks/blockTask.d.ts +5 -0
  212. package/dist/tasks/blockTask.js +12 -0
  213. package/dist/tasks/claimTask.d.ts +7 -0
  214. package/dist/tasks/claimTask.js +21 -0
  215. package/dist/tasks/completeTask.d.ts +6 -0
  216. package/dist/tasks/completeTask.js +18 -0
  217. package/dist/tasks/createTask.d.ts +6 -0
  218. package/dist/tasks/createTask.js +36 -0
  219. package/dist/tasks/getPendingTasks.d.ts +6 -0
  220. package/dist/tasks/getPendingTasks.js +19 -0
  221. package/dist/tasks/getTask.d.ts +6 -0
  222. package/dist/tasks/getTask.js +7 -0
  223. package/dist/tasks/getTasksByPlan.d.ts +6 -0
  224. package/dist/tasks/getTasksByPlan.js +11 -0
  225. package/dist/tasks/index.d.ts +11 -0
  226. package/dist/tasks/index.js +12 -0
  227. package/dist/tasks/startTask.d.ts +5 -0
  228. package/dist/tasks/startTask.js +12 -0
  229. package/dist/tasks/tasks.test.d.ts +1 -0
  230. package/dist/tasks/tasks.test.js +209 -0
  231. package/dist/tasks/types.d.ts +36 -0
  232. package/dist/tasks/types.js +1 -0
  233. package/dist/tasks/unclaimTask.d.ts +5 -0
  234. package/dist/tasks/unclaimTask.js +12 -0
  235. package/dist/test/factories/agentFactory.d.ts +13 -0
  236. package/dist/test/factories/agentFactory.js +5 -0
  237. package/dist/test/factories/eventFactory.d.ts +20 -0
  238. package/dist/test/factories/eventFactory.js +16 -0
  239. package/dist/test/factories/factories.test.d.ts +1 -0
  240. package/dist/test/factories/factories.test.js +101 -0
  241. package/dist/test/factories/index.d.ts +4 -0
  242. package/dist/test/factories/index.js +4 -0
  243. package/dist/test/factories/planFactory.d.ts +15 -0
  244. package/dist/test/factories/planFactory.js +14 -0
  245. package/dist/test/factories/taskFactory.d.ts +22 -0
  246. package/dist/test/factories/taskFactory.js +44 -0
  247. package/dist/test/multiAgentDemo.d.ts +16 -0
  248. package/dist/test/multiAgentDemo.js +20 -0
  249. package/dist/test/multiAgentDemo.test.d.ts +1 -0
  250. package/dist/test/multiAgentDemo.test.js +14 -0
  251. package/dist/test/setup.d.ts +9 -0
  252. package/dist/test/setup.js +50 -0
  253. package/dist/utils/index.d.ts +5 -0
  254. package/dist/utils/index.js +5 -0
  255. package/dist/utils/math.d.ts +6 -0
  256. package/dist/utils/math.js +10 -0
  257. package/dist/utils/math.test.d.ts +1 -0
  258. package/dist/utils/math.test.js +26 -0
  259. package/dist/utils/string.d.ts +11 -0
  260. package/dist/utils/string.js +17 -0
  261. package/dist/utils/string.test.d.ts +1 -0
  262. package/dist/utils/string.test.js +30 -0
  263. package/dist/watcher/index.d.ts +1 -0
  264. package/dist/watcher/index.js +1 -0
  265. package/dist/watcher/planWatcher.d.ts +31 -0
  266. package/dist/watcher/planWatcher.js +171 -0
  267. package/dist/worktrees/getAllWorktrees.d.ts +6 -0
  268. package/dist/worktrees/getAllWorktrees.js +10 -0
  269. package/dist/worktrees/getWorktreeById.d.ts +6 -0
  270. package/dist/worktrees/getWorktreeById.js +7 -0
  271. package/dist/worktrees/getWorktreeByPath.d.ts +6 -0
  272. package/dist/worktrees/getWorktreeByPath.js +7 -0
  273. package/dist/worktrees/index.d.ts +9 -0
  274. package/dist/worktrees/index.js +13 -0
  275. package/dist/worktrees/registerWorktree.d.ts +6 -0
  276. package/dist/worktrees/registerWorktree.js +28 -0
  277. package/dist/worktrees/removeWorktree.d.ts +6 -0
  278. package/dist/worktrees/removeWorktree.js +9 -0
  279. package/dist/worktrees/syncWorktreesFromGit.d.ts +7 -0
  280. package/dist/worktrees/syncWorktreesFromGit.js +51 -0
  281. package/dist/worktrees/types.d.ts +29 -0
  282. package/dist/worktrees/types.js +1 -0
  283. package/dist/worktrees/updateWorktreeCommit.d.ts +5 -0
  284. package/dist/worktrees/updateWorktreeCommit.js +13 -0
  285. package/dist/worktrees/updateWorktreeSeen.d.ts +5 -0
  286. package/dist/worktrees/updateWorktreeSeen.js +13 -0
  287. package/package.json +58 -0
@@ -0,0 +1,75 @@
1
+ import { existsSync } from 'fs';
2
+ import { getProjectPaths } from '../../db/getProjectPaths';
3
+ import { initializeDb } from '../../db/initializeDb';
4
+ import { formatDatetime } from '../../datetime/formatDatetime';
5
+ import { getGitInfo } from '../../git/getGitInfo';
6
+ export const setupTool = {
7
+ name: 'hivemind_setup',
8
+ description: 'Initialize hivemind for a project. Detects git repo info automatically.',
9
+ annotations: {
10
+ readOnlyHint: false,
11
+ destructiveHint: false,
12
+ idempotentHint: true,
13
+ openWorldHint: false,
14
+ },
15
+ inputSchema: {
16
+ type: 'object',
17
+ properties: {
18
+ project: {
19
+ type: 'string',
20
+ description: 'Project name. If omitted, will use git repo name or prompt.',
21
+ },
22
+ useGit: {
23
+ type: 'boolean',
24
+ description: 'Use git repo info for project name (default: true if in git repo)',
25
+ },
26
+ },
27
+ },
28
+ };
29
+ /**
30
+ * Execute setup - may return prompt for user input
31
+ */
32
+ export function executeSetup(input) {
33
+ const gitInfo = getGitInfo();
34
+ // If no project specified and we're in a git repo, ask to use it
35
+ if (!input.project && gitInfo.isRepo && input.useGit === undefined) {
36
+ return {
37
+ needsInput: true,
38
+ gitInfo: {
39
+ repoName: gitInfo.repoName,
40
+ branch: gitInfo.branch,
41
+ root: gitInfo.root,
42
+ },
43
+ message: `Git repository detected: ${gitInfo.repoName}\nUse this for project name? (set useGit: true/false)`,
44
+ };
45
+ }
46
+ // Determine project name
47
+ let projectName;
48
+ if (input.project) {
49
+ projectName = input.project;
50
+ }
51
+ else if (input.useGit !== false && gitInfo.isRepo && gitInfo.repoName) {
52
+ projectName = gitInfo.repoName;
53
+ }
54
+ else {
55
+ projectName = process.cwd().split('/').pop() || 'default';
56
+ }
57
+ // Initialize
58
+ const paths = getProjectPaths(projectName);
59
+ const isNew = !existsSync(paths.dbPath);
60
+ const db = initializeDb(projectName);
61
+ let stats = '';
62
+ if (!isNew) {
63
+ const agentCount = db.prepare('SELECT COUNT(*) as c FROM agents').get().c;
64
+ const planCount = db.prepare('SELECT COUNT(*) as c FROM plans').get().c;
65
+ const eventCount = db.prepare('SELECT COUNT(*) as c FROM events').get().c;
66
+ stats = `\nstats: ${agentCount} agents, ${planCount} plans, ${eventCount} events`;
67
+ }
68
+ db.close();
69
+ return {
70
+ needsInput: false,
71
+ project: projectName,
72
+ dbPath: paths.dbPath,
73
+ message: `hivemind ${isNew ? 'created' : 'connected'}: ${projectName}\ndb: ${paths.dbPath}${stats}\ntimestamp: ${formatDatetime()}`,
74
+ };
75
+ }
@@ -0,0 +1,44 @@
1
+ import type { Agent } from '../../agents/types';
2
+ import type { WorktreeRecord } from '../../worktrees/types';
3
+ import type { Event } from '../../events/types';
4
+ import type { Plan } from '../../plans/types';
5
+ export declare const statusTool: {
6
+ name: string;
7
+ description: string;
8
+ annotations: {
9
+ readOnlyHint: boolean;
10
+ destructiveHint: boolean;
11
+ idempotentHint: boolean;
12
+ openWorldHint: boolean;
13
+ };
14
+ inputSchema: {
15
+ type: string;
16
+ properties: {
17
+ project: {
18
+ type: string;
19
+ description: string;
20
+ };
21
+ };
22
+ required: string[];
23
+ };
24
+ };
25
+ export type StatusInput = {
26
+ project: string;
27
+ };
28
+ export type PlanWithTasks = Plan & {
29
+ taskCounts: {
30
+ pending: number;
31
+ in_progress: number;
32
+ done: number;
33
+ total: number;
34
+ };
35
+ };
36
+ export type StatusResult = {
37
+ project: string;
38
+ activeAgents: Agent[];
39
+ worktrees: WorktreeRecord[];
40
+ plans: PlanWithTasks[];
41
+ recentEvents: Event[];
42
+ summary: string;
43
+ };
44
+ export declare function executeStatus(input: StatusInput): StatusResult;
@@ -0,0 +1,74 @@
1
+ import { getConnection } from '../../db/getConnection';
2
+ import { getActiveAgents } from '../../agents/getActiveAgents';
3
+ import { getAllWorktrees } from '../../worktrees/getAllWorktrees';
4
+ import { getRecentEvents } from '../../events/getRecentEvents';
5
+ import { getActivePlans } from '../../plans/getActivePlans';
6
+ export const statusTool = {
7
+ name: 'hivemind_status',
8
+ description: 'Get current hivemind status: active agents, worktrees, recent events.',
9
+ annotations: {
10
+ readOnlyHint: true,
11
+ destructiveHint: false,
12
+ idempotentHint: true,
13
+ openWorldHint: false,
14
+ },
15
+ inputSchema: {
16
+ type: 'object',
17
+ properties: {
18
+ project: {
19
+ type: 'string',
20
+ description: 'Project name',
21
+ },
22
+ },
23
+ required: ['project'],
24
+ },
25
+ };
26
+ export function executeStatus(input) {
27
+ const db = getConnection(input.project);
28
+ const activeAgents = getActiveAgents(db);
29
+ const worktrees = getAllWorktrees(db);
30
+ const recentEvents = getRecentEvents(db, 10);
31
+ // Get active plans with task counts
32
+ const activePlans = getActivePlans(db);
33
+ const plans = activePlans.map((plan) => {
34
+ const counts = db
35
+ .prepare(`
36
+ SELECT
37
+ SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending,
38
+ SUM(CASE WHEN status = 'in_progress' THEN 1 ELSE 0 END) as in_progress,
39
+ SUM(CASE WHEN status = 'done' THEN 1 ELSE 0 END) as done,
40
+ COUNT(*) as total
41
+ FROM tasks
42
+ WHERE plan_id = ?
43
+ `)
44
+ .get(plan.id);
45
+ return {
46
+ ...plan,
47
+ taskCounts: {
48
+ pending: counts?.pending ?? 0,
49
+ in_progress: counts?.in_progress ?? 0,
50
+ done: counts?.done ?? 0,
51
+ total: counts?.total ?? 0,
52
+ },
53
+ };
54
+ });
55
+ // Count plans with open work
56
+ const plansWithWork = plans.filter((p) => p.taskCounts.pending > 0 || p.taskCounts.in_progress > 0);
57
+ const summary = [
58
+ `hivemind:${input.project}`,
59
+ `${activeAgents.length} active agent(s)`,
60
+ `${worktrees.length} worktree(s)`,
61
+ plansWithWork.length > 0 ? `${plansWithWork.length} plan(s) with open work` : null,
62
+ `${recentEvents.length} recent event(s)`,
63
+ ]
64
+ .filter(Boolean)
65
+ .join(' | ');
66
+ return {
67
+ project: input.project,
68
+ activeAgents,
69
+ worktrees,
70
+ plans,
71
+ recentEvents,
72
+ summary,
73
+ };
74
+ }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Task management MCP tools
3
+ * - Claim tasks to work on
4
+ * - Complete tasks when done
5
+ */
6
+ export declare const claimTaskTool: {
7
+ name: string;
8
+ description: string;
9
+ annotations: {
10
+ readOnlyHint: boolean;
11
+ destructiveHint: boolean;
12
+ idempotentHint: boolean;
13
+ openWorldHint: boolean;
14
+ };
15
+ inputSchema: {
16
+ type: string;
17
+ properties: {
18
+ project: {
19
+ type: string;
20
+ description: string;
21
+ };
22
+ taskId: {
23
+ type: string;
24
+ description: string;
25
+ };
26
+ agentId: {
27
+ type: string;
28
+ description: string;
29
+ };
30
+ };
31
+ required: string[];
32
+ };
33
+ };
34
+ export type ClaimTaskInput = {
35
+ project: string;
36
+ taskId: string;
37
+ agentId: string;
38
+ };
39
+ export declare function executeClaimTask(input: ClaimTaskInput): {
40
+ success: boolean;
41
+ message: string;
42
+ };
43
+ export declare const startTaskTool: {
44
+ name: string;
45
+ description: string;
46
+ annotations: {
47
+ readOnlyHint: boolean;
48
+ destructiveHint: boolean;
49
+ idempotentHint: boolean;
50
+ openWorldHint: boolean;
51
+ };
52
+ inputSchema: {
53
+ type: string;
54
+ properties: {
55
+ project: {
56
+ type: string;
57
+ description: string;
58
+ };
59
+ taskId: {
60
+ type: string;
61
+ description: string;
62
+ };
63
+ agentId: {
64
+ type: string;
65
+ description: string;
66
+ };
67
+ };
68
+ required: string[];
69
+ };
70
+ };
71
+ export type StartTaskInput = {
72
+ project: string;
73
+ taskId: string;
74
+ agentId: string;
75
+ };
76
+ export declare function executeStartTask(input: StartTaskInput): {
77
+ success: boolean;
78
+ message: string;
79
+ };
80
+ export declare const completeTaskTool: {
81
+ name: string;
82
+ description: string;
83
+ annotations: {
84
+ readOnlyHint: boolean;
85
+ destructiveHint: boolean;
86
+ idempotentHint: boolean;
87
+ openWorldHint: boolean;
88
+ };
89
+ inputSchema: {
90
+ type: string;
91
+ properties: {
92
+ project: {
93
+ type: string;
94
+ description: string;
95
+ };
96
+ taskId: {
97
+ type: string;
98
+ description: string;
99
+ };
100
+ agentId: {
101
+ type: string;
102
+ description: string;
103
+ };
104
+ };
105
+ required: string[];
106
+ };
107
+ };
108
+ export type CompleteTaskInput = {
109
+ project: string;
110
+ taskId: string;
111
+ agentId: string;
112
+ };
113
+ export declare function executeCompleteTask(input: CompleteTaskInput): {
114
+ success: boolean;
115
+ message: string;
116
+ };
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Task management MCP tools
3
+ * - Claim tasks to work on
4
+ * - Complete tasks when done
5
+ */
6
+ import { getConnection } from '../../db/getConnection';
7
+ import { getTask } from '../../tasks/getTask';
8
+ import { claimTask } from '../../tasks/claimTask';
9
+ import { completeTask } from '../../tasks/completeTask';
10
+ import { startTask } from '../../tasks/startTask';
11
+ import { emit } from '../../events/emit';
12
+ // ─────────────────────────────────────────────────────────────
13
+ // Claim Task
14
+ // ─────────────────────────────────────────────────────────────
15
+ export const claimTaskTool = {
16
+ name: 'hivemind_claim_task',
17
+ description: 'Claim a task to work on. Other agents will see you own this task.',
18
+ annotations: {
19
+ readOnlyHint: false,
20
+ destructiveHint: false,
21
+ idempotentHint: true,
22
+ openWorldHint: false,
23
+ },
24
+ inputSchema: {
25
+ type: 'object',
26
+ properties: {
27
+ project: { type: 'string', description: 'Project name' },
28
+ taskId: { type: 'string', description: 'Task ID to claim' },
29
+ agentId: { type: 'string', description: 'Your agent ID' },
30
+ },
31
+ required: ['project', 'taskId', 'agentId'],
32
+ },
33
+ };
34
+ export function executeClaimTask(input) {
35
+ const db = getConnection(input.project);
36
+ const task = getTask(db, input.taskId);
37
+ if (!task) {
38
+ return { success: false, message: `Task ${input.taskId} not found` };
39
+ }
40
+ if (task.status === 'done') {
41
+ return { success: false, message: `Task ${input.taskId} is already done` };
42
+ }
43
+ if (task.claimed_by && task.claimed_by !== input.agentId) {
44
+ return { success: false, message: `Task ${input.taskId} is claimed by ${task.claimed_by}` };
45
+ }
46
+ const result = claimTask(db, input.taskId, input.agentId);
47
+ if (!result) {
48
+ return { success: false, message: `Failed to claim task ${input.taskId}` };
49
+ }
50
+ emit(db, {
51
+ type: 'task:claim',
52
+ content: `${input.agentId} claimed: ${task.title}`,
53
+ agent_id: input.agentId,
54
+ task_id: input.taskId,
55
+ plan_id: task.plan_id,
56
+ });
57
+ return { success: true, message: `Claimed task: ${task.title}` };
58
+ }
59
+ // ─────────────────────────────────────────────────────────────
60
+ // Start Task (mark in progress)
61
+ // ─────────────────────────────────────────────────────────────
62
+ export const startTaskTool = {
63
+ name: 'hivemind_start_task',
64
+ description: 'Mark a task as in progress. Call after claiming when you begin work.',
65
+ annotations: {
66
+ readOnlyHint: false,
67
+ destructiveHint: false,
68
+ idempotentHint: true,
69
+ openWorldHint: false,
70
+ },
71
+ inputSchema: {
72
+ type: 'object',
73
+ properties: {
74
+ project: { type: 'string', description: 'Project name' },
75
+ taskId: { type: 'string', description: 'Task ID to start' },
76
+ agentId: { type: 'string', description: 'Your agent ID' },
77
+ },
78
+ required: ['project', 'taskId', 'agentId'],
79
+ },
80
+ };
81
+ export function executeStartTask(input) {
82
+ const db = getConnection(input.project);
83
+ const task = getTask(db, input.taskId);
84
+ if (!task) {
85
+ return { success: false, message: `Task ${input.taskId} not found` };
86
+ }
87
+ if (task.status === 'done') {
88
+ return { success: false, message: `Task ${input.taskId} is already done` };
89
+ }
90
+ startTask(db, input.taskId);
91
+ emit(db, {
92
+ type: 'task:start',
93
+ content: `${input.agentId} started: ${task.title}`,
94
+ agent_id: input.agentId,
95
+ task_id: input.taskId,
96
+ plan_id: task.plan_id,
97
+ });
98
+ return { success: true, message: `Started task: ${task.title}` };
99
+ }
100
+ // ─────────────────────────────────────────────────────────────
101
+ // Complete Task
102
+ // ─────────────────────────────────────────────────────────────
103
+ export const completeTaskTool = {
104
+ name: 'hivemind_complete_task',
105
+ description: 'Mark a task as done.',
106
+ annotations: {
107
+ readOnlyHint: false,
108
+ destructiveHint: false,
109
+ idempotentHint: true,
110
+ openWorldHint: false,
111
+ },
112
+ inputSchema: {
113
+ type: 'object',
114
+ properties: {
115
+ project: { type: 'string', description: 'Project name' },
116
+ taskId: { type: 'string', description: 'Task ID to complete' },
117
+ agentId: { type: 'string', description: 'Your agent ID' },
118
+ },
119
+ required: ['project', 'taskId', 'agentId'],
120
+ },
121
+ };
122
+ export function executeCompleteTask(input) {
123
+ const db = getConnection(input.project);
124
+ const task = getTask(db, input.taskId);
125
+ if (!task) {
126
+ return { success: false, message: `Task ${input.taskId} not found` };
127
+ }
128
+ if (task.status === 'done') {
129
+ return { success: false, message: `Task ${input.taskId} is already done` };
130
+ }
131
+ const result = completeTask(db, input.taskId);
132
+ if (!result) {
133
+ return { success: false, message: `Failed to complete task ${input.taskId}` };
134
+ }
135
+ emit(db, {
136
+ type: 'task:complete',
137
+ content: `${input.agentId} completed: ${task.title}`,
138
+ agent_id: input.agentId,
139
+ task_id: input.taskId,
140
+ plan_id: task.plan_id,
141
+ });
142
+ return { success: true, message: `Completed task: ${task.title}` };
143
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * hivemind_worktree_cleanup - Clean up stale worktrees
3
+ */
4
+ export declare const worktreeCleanupTool: {
5
+ name: string;
6
+ description: string;
7
+ annotations: {
8
+ readOnlyHint: boolean;
9
+ destructiveHint: boolean;
10
+ idempotentHint: boolean;
11
+ openWorldHint: boolean;
12
+ };
13
+ inputSchema: {
14
+ type: "object";
15
+ properties: {
16
+ project: {
17
+ type: string;
18
+ description: string;
19
+ };
20
+ dryRun: {
21
+ type: string;
22
+ description: string;
23
+ };
24
+ };
25
+ required: string[];
26
+ };
27
+ };
28
+ export type WorktreeCleanupInput = {
29
+ project: string;
30
+ dryRun?: boolean;
31
+ };
32
+ export type WorktreeCleanupResult = {
33
+ checked: number;
34
+ removed: string[];
35
+ kept: string[];
36
+ dryRun: boolean;
37
+ };
38
+ export declare function executeWorktreeCleanup(input: WorktreeCleanupInput): WorktreeCleanupResult;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * hivemind_worktree_cleanup - Clean up stale worktrees
3
+ */
4
+ import { existsSync } from 'fs';
5
+ import { getConnection } from '../../db/getConnection';
6
+ import { getAllWorktrees } from '../../worktrees/getAllWorktrees';
7
+ import { removeWorktree } from '../../worktrees/removeWorktree';
8
+ import { emit } from '../../events/emit';
9
+ export const worktreeCleanupTool = {
10
+ name: 'hivemind_worktree_cleanup',
11
+ description: 'Clean up stale worktrees from hivemind database',
12
+ annotations: {
13
+ readOnlyHint: false,
14
+ destructiveHint: true,
15
+ idempotentHint: true,
16
+ openWorldHint: false,
17
+ },
18
+ inputSchema: {
19
+ type: 'object',
20
+ properties: {
21
+ project: {
22
+ type: 'string',
23
+ description: 'Project name',
24
+ },
25
+ dryRun: {
26
+ type: 'boolean',
27
+ description: 'Preview without deleting',
28
+ },
29
+ },
30
+ required: ['project'],
31
+ },
32
+ };
33
+ export function executeWorktreeCleanup(input) {
34
+ const db = getConnection(input.project);
35
+ const worktrees = getAllWorktrees(db);
36
+ const removed = [];
37
+ const kept = [];
38
+ for (const wt of worktrees) {
39
+ const exists = existsSync(wt.path);
40
+ if (!exists) {
41
+ if (!input.dryRun) {
42
+ removeWorktree(db, wt.id);
43
+ emit(db, {
44
+ type: 'worktree:stale',
45
+ worktree_id: wt.id,
46
+ branch: wt.branch ?? undefined,
47
+ content: `Worktree removed: ${wt.path} (path gone)`,
48
+ metadata: {
49
+ path: wt.path,
50
+ branch: wt.branch,
51
+ last_seen: wt.last_seen,
52
+ },
53
+ });
54
+ }
55
+ removed.push(`${wt.id} (${wt.path})`);
56
+ }
57
+ else {
58
+ kept.push(`${wt.id} (${wt.path})`);
59
+ }
60
+ }
61
+ return {
62
+ checked: worktrees.length,
63
+ removed,
64
+ kept,
65
+ dryRun: input.dryRun ?? false,
66
+ };
67
+ }
@@ -0,0 +1,6 @@
1
+ import type { Database } from 'bun:sqlite';
2
+ import type { Plan, CreatePlanInput } from './types';
3
+ /**
4
+ * Create a new plan
5
+ */
6
+ export declare function createPlan(db: Database, input: CreatePlanInput): Plan;
@@ -0,0 +1,29 @@
1
+ import { makePlanId } from '../ids/makePlanId';
2
+ import { sanitizeLabel } from '../ids/sanitizeLabel';
3
+ import { now } from '../datetime/now';
4
+ /**
5
+ * Create a new plan
6
+ */
7
+ export function createPlan(db, input) {
8
+ const { id, hex } = makePlanId(input.label);
9
+ const label = input.label ? sanitizeLabel(input.label) : null;
10
+ const timestamp = now();
11
+ const stmt = db.prepare(`
12
+ INSERT INTO plans (id, hex, label, title, description, status, branch, worktree_id, claude_session_id, created_at, created_by)
13
+ VALUES (?, ?, ?, ?, ?, 'active', ?, ?, ?, ?, ?)
14
+ `);
15
+ stmt.run(id, hex, label, input.title, input.description ?? null, input.branch ?? null, input.worktree_id ?? null, input.claude_session_id ?? null, timestamp, input.created_by ?? null);
16
+ return {
17
+ id,
18
+ hex,
19
+ label,
20
+ title: input.title,
21
+ description: input.description ?? null,
22
+ status: 'active',
23
+ branch: input.branch ?? null,
24
+ worktree_id: input.worktree_id ?? null,
25
+ claude_session_id: input.claude_session_id ?? null,
26
+ created_at: timestamp,
27
+ created_by: input.created_by ?? null,
28
+ };
29
+ }
@@ -0,0 +1,6 @@
1
+ import type { Database } from 'bun:sqlite';
2
+ import type { Plan } from './types';
3
+ /**
4
+ * Get all active plans
5
+ */
6
+ export declare function getActivePlans(db: Database): Plan[];
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Get all active plans
3
+ */
4
+ export function getActivePlans(db) {
5
+ const stmt = db.prepare(`
6
+ SELECT * FROM plans
7
+ WHERE status = 'active'
8
+ ORDER BY created_at DESC
9
+ `);
10
+ return stmt.all();
11
+ }
@@ -0,0 +1,6 @@
1
+ import type { Database } from 'bun:sqlite';
2
+ import type { Plan } from './types';
3
+ /**
4
+ * Get a plan by ID
5
+ */
6
+ export declare function getPlan(db: Database, planId: string): Plan | null;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Get a plan by ID
3
+ */
4
+ export function getPlan(db, planId) {
5
+ const stmt = db.prepare('SELECT * FROM plans WHERE id = ?');
6
+ return stmt.get(planId) ?? null;
7
+ }
@@ -0,0 +1,5 @@
1
+ export type { PlanStatus, Plan, CreatePlanInput } from './types';
2
+ export { createPlan } from './createPlan';
3
+ export { getPlan } from './getPlan';
4
+ export { getActivePlans } from './getActivePlans';
5
+ export { updatePlanStatus } from './updatePlanStatus';
@@ -0,0 +1,5 @@
1
+ // CRUD
2
+ export { createPlan } from './createPlan';
3
+ export { getPlan } from './getPlan';
4
+ export { getActivePlans } from './getActivePlans';
5
+ export { updatePlanStatus } from './updatePlanStatus';
@@ -0,0 +1 @@
1
+ export {};