kitty-hive 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.
@@ -0,0 +1,222 @@
1
+ import { getAgentById, getAgentByName, findAgentByRole, createTask, getTaskById, updateTaskStatus, appendTaskEvent, getTaskEvents, getPeerByName, } from '../db.js';
2
+ import { validateWorkflowTransition, shouldAdvanceStep, getRejectTarget } from '../state-machine.js';
3
+ export function handleTaskCreate(actorId, input) {
4
+ let assignee;
5
+ if (input.to) {
6
+ if (input.to.startsWith('role:')) {
7
+ const agent = findAgentByRole(input.to.slice(5));
8
+ if (agent)
9
+ assignee = { id: agent.id, display_name: agent.display_name };
10
+ }
11
+ else {
12
+ const agent = getAgentById(input.to) || getAgentByName(input.to);
13
+ if (agent)
14
+ assignee = { id: agent.id, display_name: agent.display_name };
15
+ }
16
+ }
17
+ const task = createTask(input.title, actorId, assignee?.id, input.source_room_id, input.input);
18
+ // task-start → proposing (assignee should propose workflow)
19
+ validateWorkflowTransition('created', 'task-start');
20
+ appendTaskEvent(task.id, 'task-start', actorId, {
21
+ title: input.title, input: input.input, assignee_agent_id: assignee?.id ?? null,
22
+ });
23
+ let status = assignee ? 'proposing' : 'created';
24
+ updateTaskStatus(task.id, status, assignee ? { assignee_agent_id: assignee.id } : {});
25
+ return { task_id: task.id, title: task.title, status, assignee };
26
+ }
27
+ // --- Federated task ---
28
+ function parseTarget(to) {
29
+ const at = to.lastIndexOf('@');
30
+ if (at > 0)
31
+ return { agent: to.slice(0, at), node: to.slice(at + 1) };
32
+ return { agent: to };
33
+ }
34
+ export async function handleTaskCreateAsync(actorId, input) {
35
+ if (!input.to)
36
+ return handleTaskCreate(actorId, input);
37
+ const { agent: targetName, node } = parseTarget(input.to);
38
+ if (!node)
39
+ return handleTaskCreate(actorId, { ...input, to: targetName });
40
+ // Federated task
41
+ const peer = getPeerByName(node);
42
+ if (!peer)
43
+ throw new Error(`Peer "${node}" not found`);
44
+ const actor = getAgentById(actorId);
45
+ const fromName = actor?.display_name ?? actorId;
46
+ const res = await fetch(peer.url.replace('/mcp', '/federation/task'), {
47
+ method: 'POST',
48
+ headers: {
49
+ 'Content-Type': 'application/json',
50
+ 'Authorization': `Bearer ${peer.secret}`,
51
+ 'X-Hive-Peer': node,
52
+ },
53
+ body: JSON.stringify({ from: fromName, to: targetName, title: input.title, input: input.input }),
54
+ });
55
+ if (!res.ok) {
56
+ const err = await res.json().catch(() => ({ error: res.statusText }));
57
+ throw new Error(`Federation task failed: ${err.error || res.statusText}`);
58
+ }
59
+ const result = await res.json();
60
+ return {
61
+ task_id: result.task_id, title: input.title,
62
+ status: result.status,
63
+ assignee: { id: targetName, display_name: `${targetName}@${node}` },
64
+ };
65
+ }
66
+ // --- Federated task event ---
67
+ export async function sendFederatedTaskEvent(taskId, peerNode, fromName, type, extras = {}) {
68
+ const peer = getPeerByName(peerNode);
69
+ if (!peer)
70
+ throw new Error(`Peer "${peerNode}" not found`);
71
+ const res = await fetch(peer.url.replace('/mcp', '/federation/task/event'), {
72
+ method: 'POST',
73
+ headers: {
74
+ 'Content-Type': 'application/json',
75
+ 'Authorization': `Bearer ${peer.secret}`,
76
+ 'X-Hive-Peer': peerNode,
77
+ },
78
+ body: JSON.stringify({ from: fromName, task_id: taskId, type, ...extras }),
79
+ });
80
+ if (!res.ok) {
81
+ const err = await res.json().catch(() => ({ error: res.statusText }));
82
+ throw new Error(`Federation task event failed: ${err.error || res.statusText}`);
83
+ }
84
+ return res.json();
85
+ }
86
+ // --- hive.task.claim ---
87
+ export function handleTaskClaim(taskId, agentId) {
88
+ const task = getTaskById(taskId);
89
+ if (!task)
90
+ throw new Error(`Task not found: ${taskId}`);
91
+ if (task.status !== 'created')
92
+ throw new Error(`Task cannot be claimed (status: ${task.status})`);
93
+ if (task.assignee_agent_id)
94
+ throw new Error('Task already has an assignee');
95
+ const agent = getAgentById(agentId);
96
+ if (!agent)
97
+ throw new Error('Agent not found');
98
+ // Claim → proposing (agent should propose workflow next)
99
+ const status = 'proposing';
100
+ appendTaskEvent(taskId, 'task-claim', agentId, {});
101
+ updateTaskStatus(taskId, status, { assignee_agent_id: agentId });
102
+ return {
103
+ task_id: taskId, title: task.title, status,
104
+ assignee: { id: agent.id, display_name: agent.display_name },
105
+ };
106
+ }
107
+ export function handleCheck(input) {
108
+ const task = getTaskById(input.task_id);
109
+ if (!task)
110
+ throw new Error(`Task not found: ${input.task_id}`);
111
+ const events = getTaskEvents(task.id);
112
+ let assignee;
113
+ if (task.assignee_agent_id) {
114
+ const agent = getAgentById(task.assignee_agent_id);
115
+ if (agent)
116
+ assignee = { id: agent.id, display_name: agent.display_name };
117
+ }
118
+ let workflow;
119
+ if (task.workflow_json) {
120
+ workflow = { current_step: task.current_step, steps: JSON.parse(task.workflow_json) };
121
+ }
122
+ return {
123
+ task_id: task.id, title: task.title, status: task.status,
124
+ assignee, recent_events: events.slice(-10), workflow,
125
+ };
126
+ }
127
+ // --- Workflow: propose ---
128
+ export function handleWorkflowPropose(taskId, agentId, workflow) {
129
+ const task = getTaskById(taskId);
130
+ if (!task)
131
+ throw new Error(`Task not found: ${taskId}`);
132
+ if (task.creator_agent_id !== agentId && task.assignee_agent_id !== agentId)
133
+ throw new Error('Only the task creator or assignee can propose a workflow');
134
+ validateWorkflowTransition(task.status, 'task-propose');
135
+ const steps = workflow.map(s => ({ ...s, completed_by: [] }));
136
+ updateTaskStatus(taskId, 'proposing', { workflow_json: JSON.stringify(steps) });
137
+ appendTaskEvent(taskId, 'task-propose', agentId, { workflow: steps });
138
+ }
139
+ export function handleWorkflowApprove(taskId, agentId) {
140
+ const task = getTaskById(taskId);
141
+ if (!task)
142
+ throw new Error(`Task not found: ${taskId}`);
143
+ if (task.creator_agent_id !== agentId)
144
+ throw new Error('Only the task creator can approve the workflow');
145
+ if (!task.workflow_json)
146
+ throw new Error('No workflow defined');
147
+ const steps = JSON.parse(task.workflow_json);
148
+ if (steps.length === 0)
149
+ throw new Error('Workflow has no steps');
150
+ // proposing → approved
151
+ validateWorkflowTransition(task.status, 'task-approve');
152
+ updateTaskStatus(taskId, 'approved');
153
+ appendTaskEvent(taskId, 'task-approve', agentId, {});
154
+ // approved → in_progress (step-start)
155
+ validateWorkflowTransition('approved', 'step-start');
156
+ updateTaskStatus(taskId, 'in_progress', { current_step: 1 });
157
+ appendTaskEvent(taskId, 'step-start', null, { step: 1, assignees: steps[0].assignees });
158
+ return { type: 'step-start', step: 1, assignees: steps[0].assignees };
159
+ }
160
+ // --- Workflow: step complete ---
161
+ export function handleStepComplete(taskId, agentId, stepNum, result) {
162
+ const task = getTaskById(taskId);
163
+ if (!task)
164
+ throw new Error(`Task not found: ${taskId}`);
165
+ if (!task.workflow_json)
166
+ throw new Error('No workflow defined');
167
+ if (task.current_step !== stepNum)
168
+ throw new Error(`Step ${stepNum} is not current (current: ${task.current_step})`);
169
+ validateWorkflowTransition(task.status, 'step-complete');
170
+ const steps = JSON.parse(task.workflow_json);
171
+ const step = steps.find(s => s.step === stepNum);
172
+ if (!step)
173
+ throw new Error(`Step ${stepNum} not found`);
174
+ if (!step.completed_by.includes(agentId)) {
175
+ step.completed_by.push(agentId);
176
+ }
177
+ appendTaskEvent(taskId, 'step-complete', agentId, { step: stepNum, result });
178
+ updateTaskStatus(taskId, task.status, { workflow_json: JSON.stringify(steps) });
179
+ if (shouldAdvanceStep(step)) {
180
+ const nextStepNum = stepNum + 1;
181
+ if (nextStepNum > steps.length) {
182
+ validateWorkflowTransition(task.status, 'task-complete');
183
+ updateTaskStatus(taskId, 'completed', { completed_at: new Date().toISOString() });
184
+ appendTaskEvent(taskId, 'task-complete', null, {});
185
+ return { type: 'task-complete' };
186
+ }
187
+ else {
188
+ const nextStep = steps[nextStepNum - 1];
189
+ updateTaskStatus(taskId, 'in_progress', { current_step: nextStepNum });
190
+ appendTaskEvent(taskId, 'step-start', null, {
191
+ step: nextStepNum, assignees: nextStep.assignees,
192
+ previous_step_result: result,
193
+ });
194
+ return { type: 'step-start', step: nextStepNum, assignees: nextStep.assignees };
195
+ }
196
+ }
197
+ return null;
198
+ }
199
+ // --- Workflow: reject ---
200
+ export function handleWorkflowReject(taskId, agentId, stepNum, reason) {
201
+ const task = getTaskById(taskId);
202
+ if (!task)
203
+ throw new Error(`Task not found: ${taskId}`);
204
+ if (!task.workflow_json)
205
+ throw new Error('No workflow defined');
206
+ validateWorkflowTransition(task.status, 'task-reject');
207
+ const steps = JSON.parse(task.workflow_json);
208
+ const step = steps.find(s => s.step === stepNum);
209
+ if (!step)
210
+ throw new Error(`Step ${stepNum} not found`);
211
+ const targetStep = getRejectTarget(step);
212
+ for (const s of steps) {
213
+ if (s.step >= targetStep)
214
+ s.completed_by = [];
215
+ }
216
+ updateTaskStatus(taskId, 'in_progress', { current_step: targetStep, workflow_json: JSON.stringify(steps) });
217
+ appendTaskEvent(taskId, 'task-reject', agentId, { step: stepNum, target_step: targetStep, reason });
218
+ const target = steps.find(s => s.step === targetStep);
219
+ appendTaskEvent(taskId, 'step-start', null, { step: targetStep, assignees: target?.assignees || [] });
220
+ return { type: 'step-start', step: targetStep, assignees: target?.assignees || [] };
221
+ }
222
+ //# sourceMappingURL=task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.js","sourceRoot":"","sources":["../../src/tools/task.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ interface CreateInput {
2
+ name: string;
3
+ }
4
+ export declare function handleTeamCreate(actorId: string, input: CreateInput): {
5
+ room_id: string;
6
+ name: string;
7
+ };
8
+ interface JoinInput {
9
+ room_id?: string;
10
+ name?: string;
11
+ }
12
+ export declare function handleTeamJoin(actorId: string, input: JoinInput): {
13
+ room_id: string;
14
+ name: string | null;
15
+ };
16
+ interface TeamSummary {
17
+ room_id: string;
18
+ name: string | null;
19
+ member_count: number;
20
+ members: string[];
21
+ }
22
+ export declare function handleTeamList(): {
23
+ teams: TeamSummary[];
24
+ };
25
+ export {};
@@ -0,0 +1,44 @@
1
+ import { createRoom, appendRoomEvent, getRoomById, isMember, listTeams, getRoomMembers, getAgentById } from '../db.js';
2
+ export function handleTeamCreate(actorId, input) {
3
+ // Check uniqueness
4
+ const existing = listTeams().find(t => t.name === input.name);
5
+ if (existing)
6
+ throw new Error(`Team "${input.name}" already exists (room_id: ${existing.id})`);
7
+ const room = createRoom('team', actorId, input.name);
8
+ appendRoomEvent(room.id, 'join', actorId);
9
+ return { room_id: room.id, name: input.name };
10
+ }
11
+ export function handleTeamJoin(actorId, input) {
12
+ let room;
13
+ if (input.room_id) {
14
+ room = getRoomById(input.room_id);
15
+ }
16
+ else if (input.name) {
17
+ const teams = listTeams();
18
+ room = teams.find(t => t.name === input.name);
19
+ }
20
+ if (!room)
21
+ throw new Error(`Team not found: ${input.room_id || input.name}`);
22
+ if (room.kind !== 'team')
23
+ throw new Error('Not a team room');
24
+ if (room.closed_at)
25
+ throw new Error('Team is closed');
26
+ if (isMember(room.id, actorId))
27
+ throw new Error('Already a member');
28
+ appendRoomEvent(room.id, 'join', actorId);
29
+ return { room_id: room.id, name: room.name };
30
+ }
31
+ export function handleTeamList() {
32
+ const teams = listTeams();
33
+ return {
34
+ teams: teams.map(t => {
35
+ const memberIds = getRoomMembers(t.id);
36
+ const members = memberIds.map(id => {
37
+ const agent = getAgentById(id);
38
+ return agent?.display_name ?? id;
39
+ });
40
+ return { room_id: t.id, name: t.name, member_count: memberIds.length, members };
41
+ }),
42
+ };
43
+ }
44
+ //# sourceMappingURL=team.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team.js","sourceRoot":"","sources":["../../src/tools/team.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AASvH,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,KAAkB;IAClE,mBAAmB;IACnB,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9D,IAAI,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,SAAS,KAAK,CAAC,IAAI,8BAA8B,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC;IAE/F,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACrD,eAAe,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;AAChD,CAAC;AASD,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,KAAgB;IAC9D,IAAI,IAAI,CAAC;IACT,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;SAAM,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;QAC1B,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7E,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC7D,IAAI,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACtD,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAEpE,eAAe,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;AAC/C,CAAC;AAWD,MAAM,UAAU,cAAc;IAC5B,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YACnB,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACvC,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;gBACjC,MAAM,KAAK,GAAG,YAAY,CAAC,EAAE,CAAC,CAAC;gBAC/B,OAAO,KAAK,EAAE,YAAY,IAAI,EAAE,CAAC;YACnC,CAAC,CAAC,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,YAAY,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;QAClF,CAAC,CAAC;KACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function ulid(): string;
2
+ export declare function generateToken(): string;
3
+ export declare function nowISO(): string;
package/dist/utils.js ADDED
@@ -0,0 +1,14 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ // Simple ULID-like ID: timestamp prefix + random suffix (sortable, unique)
3
+ export function ulid() {
4
+ const ts = Date.now().toString(36).padStart(9, '0');
5
+ const rand = randomBytes(8).toString('hex');
6
+ return `${ts}-${rand}`;
7
+ }
8
+ export function generateToken() {
9
+ return randomBytes(32).toString('hex');
10
+ }
11
+ export function nowISO() {
12
+ return new Date().toISOString();
13
+ }
14
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,2EAA2E;AAC3E,MAAM,UAAU,IAAI;IAClB,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,OAAO,GAAG,EAAE,IAAI,IAAI,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,MAAM;IACpB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "kitty-hive",
3
+ "version": "0.1.0",
4
+ "description": "Room-first MCP server for multi-agent collaboration",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "kitty-hive": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist/",
12
+ "channel.ts",
13
+ "README.md",
14
+ "README.zh.md"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "dev": "tsc --watch",
19
+ "start": "node dist/index.js serve",
20
+ "prepublishOnly": "npm run build",
21
+ "test": "node --test dist/**/*.test.js"
22
+ },
23
+ "keywords": [
24
+ "mcp",
25
+ "multi-agent",
26
+ "collaboration",
27
+ "ai-agent",
28
+ "streamable-http",
29
+ "claude-code"
30
+ ],
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/seangx/kitty-hive"
34
+ },
35
+ "license": "MIT",
36
+ "dependencies": {
37
+ "@modelcontextprotocol/sdk": "^1.12.0",
38
+ "better-sqlite3": "^11.8.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/better-sqlite3": "^7.6.12",
42
+ "@types/node": "^22.0.0",
43
+ "typescript": "^5.7.0"
44
+ }
45
+ }