@studiomopoke/crosschat 1.6.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/LICENSE +62 -0
- package/README.md +279 -0
- package/bin/cli.cjs +631 -0
- package/crosschat.md +196 -0
- package/dashboard/dist/assets/index-Blgmbgo_.css +1 -0
- package/dashboard/dist/assets/index-DzcjxzDR.js +49 -0
- package/dashboard/dist/index.html +13 -0
- package/dist/dashboard/dashboard-listener.d.ts +22 -0
- package/dist/dashboard/dashboard-listener.d.ts.map +1 -0
- package/dist/dashboard/dashboard-listener.js +124 -0
- package/dist/dashboard/dashboard-listener.js.map +1 -0
- package/dist/dashboard/http-server.d.ts +25 -0
- package/dist/dashboard/http-server.d.ts.map +1 -0
- package/dist/dashboard/http-server.js +281 -0
- package/dist/dashboard/http-server.js.map +1 -0
- package/dist/dashboard/message-bridge.d.ts +19 -0
- package/dist/dashboard/message-bridge.d.ts.map +1 -0
- package/dist/dashboard/message-bridge.js +48 -0
- package/dist/dashboard/message-bridge.js.map +1 -0
- package/dist/hub/agent-connection.d.ts +101 -0
- package/dist/hub/agent-connection.d.ts.map +1 -0
- package/dist/hub/agent-connection.js +383 -0
- package/dist/hub/agent-connection.js.map +1 -0
- package/dist/hub/hub-main.d.ts +2 -0
- package/dist/hub/hub-main.d.ts.map +1 -0
- package/dist/hub/hub-main.js +16 -0
- package/dist/hub/hub-main.js.map +1 -0
- package/dist/hub/hub-server.d.ts +8 -0
- package/dist/hub/hub-server.d.ts.map +1 -0
- package/dist/hub/hub-server.js +1500 -0
- package/dist/hub/hub-server.js.map +1 -0
- package/dist/hub/protocol.d.ts +221 -0
- package/dist/hub/protocol.d.ts.map +1 -0
- package/dist/hub/protocol.js +20 -0
- package/dist/hub/protocol.js.map +1 -0
- package/dist/hub/task-manager.d.ts +68 -0
- package/dist/hub/task-manager.d.ts.map +1 -0
- package/dist/hub/task-manager.js +250 -0
- package/dist/hub/task-manager.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle.d.ts +2 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +234 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/prompts.d.ts +3 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +48 -0
- package/dist/prompts.js.map +1 -0
- package/dist/registry/cleanup.d.ts +2 -0
- package/dist/registry/cleanup.d.ts.map +1 -0
- package/dist/registry/cleanup.js +60 -0
- package/dist/registry/cleanup.js.map +1 -0
- package/dist/registry/registry.d.ts +11 -0
- package/dist/registry/registry.d.ts.map +1 -0
- package/dist/registry/registry.js +82 -0
- package/dist/registry/registry.js.map +1 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +91 -0
- package/dist/server.js.map +1 -0
- package/dist/stores/message-store.d.ts +21 -0
- package/dist/stores/message-store.d.ts.map +1 -0
- package/dist/stores/message-store.js +83 -0
- package/dist/stores/message-store.js.map +1 -0
- package/dist/stores/task-store.d.ts +15 -0
- package/dist/stores/task-store.d.ts.map +1 -0
- package/dist/stores/task-store.js +57 -0
- package/dist/stores/task-store.js.map +1 -0
- package/dist/tools/accept-claim.d.ts +4 -0
- package/dist/tools/accept-claim.d.ts.map +1 -0
- package/dist/tools/accept-claim.js +27 -0
- package/dist/tools/accept-claim.js.map +1 -0
- package/dist/tools/chat-send.d.ts +4 -0
- package/dist/tools/chat-send.d.ts.map +1 -0
- package/dist/tools/chat-send.js +19 -0
- package/dist/tools/chat-send.js.map +1 -0
- package/dist/tools/claim-task.d.ts +4 -0
- package/dist/tools/claim-task.d.ts.map +1 -0
- package/dist/tools/claim-task.js +26 -0
- package/dist/tools/claim-task.js.map +1 -0
- package/dist/tools/clear-session.d.ts +5 -0
- package/dist/tools/clear-session.d.ts.map +1 -0
- package/dist/tools/clear-session.js +41 -0
- package/dist/tools/clear-session.js.map +1 -0
- package/dist/tools/complete-task.d.ts +4 -0
- package/dist/tools/complete-task.d.ts.map +1 -0
- package/dist/tools/complete-task.js +29 -0
- package/dist/tools/complete-task.js.map +1 -0
- package/dist/tools/create-room.d.ts +4 -0
- package/dist/tools/create-room.d.ts.map +1 -0
- package/dist/tools/create-room.js +28 -0
- package/dist/tools/create-room.js.map +1 -0
- package/dist/tools/delegate-task.d.ts +4 -0
- package/dist/tools/delegate-task.d.ts.map +1 -0
- package/dist/tools/delegate-task.js +32 -0
- package/dist/tools/delegate-task.js.map +1 -0
- package/dist/tools/get-messages.d.ts +4 -0
- package/dist/tools/get-messages.d.ts.map +1 -0
- package/dist/tools/get-messages.js +35 -0
- package/dist/tools/get-messages.js.map +1 -0
- package/dist/tools/get-room-digest.d.ts +4 -0
- package/dist/tools/get-room-digest.d.ts.map +1 -0
- package/dist/tools/get-room-digest.js +63 -0
- package/dist/tools/get-room-digest.js.map +1 -0
- package/dist/tools/get-task-status.d.ts +4 -0
- package/dist/tools/get-task-status.d.ts.map +1 -0
- package/dist/tools/get-task-status.js +26 -0
- package/dist/tools/get-task-status.js.map +1 -0
- package/dist/tools/join-room.d.ts +4 -0
- package/dist/tools/join-room.d.ts.map +1 -0
- package/dist/tools/join-room.js +26 -0
- package/dist/tools/join-room.js.map +1 -0
- package/dist/tools/list-peers.d.ts +4 -0
- package/dist/tools/list-peers.d.ts.map +1 -0
- package/dist/tools/list-peers.js +26 -0
- package/dist/tools/list-peers.js.map +1 -0
- package/dist/tools/list-tasks.d.ts +4 -0
- package/dist/tools/list-tasks.d.ts.map +1 -0
- package/dist/tools/list-tasks.js +28 -0
- package/dist/tools/list-tasks.js.map +1 -0
- package/dist/tools/send-message.d.ts +4 -0
- package/dist/tools/send-message.d.ts.map +1 -0
- package/dist/tools/send-message.js +28 -0
- package/dist/tools/send-message.js.map +1 -0
- package/dist/tools/set-status.d.ts +4 -0
- package/dist/tools/set-status.d.ts.map +1 -0
- package/dist/tools/set-status.js +28 -0
- package/dist/tools/set-status.js.map +1 -0
- package/dist/tools/update-task.d.ts +4 -0
- package/dist/tools/update-task.d.ts.map +1 -0
- package/dist/tools/update-task.js +28 -0
- package/dist/tools/update-task.js.map +1 -0
- package/dist/tools/wait-for-messages.d.ts +4 -0
- package/dist/tools/wait-for-messages.d.ts.map +1 -0
- package/dist/tools/wait-for-messages.js +84 -0
- package/dist/tools/wait-for-messages.js.map +1 -0
- package/dist/transport/peer-protocol.d.ts +7 -0
- package/dist/transport/peer-protocol.d.ts.map +1 -0
- package/dist/transport/peer-protocol.js +30 -0
- package/dist/transport/peer-protocol.js.map +1 -0
- package/dist/transport/uds-client.d.ts +3 -0
- package/dist/transport/uds-client.d.ts.map +1 -0
- package/dist/transport/uds-client.js +57 -0
- package/dist/transport/uds-client.js.map +1 -0
- package/dist/transport/uds-server.d.ts +12 -0
- package/dist/transport/uds-server.d.ts.map +1 -0
- package/dist/transport/uds-server.js +87 -0
- package/dist/transport/uds-server.js.map +1 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/util/id.d.ts +2 -0
- package/dist/util/id.d.ts.map +1 -0
- package/dist/util/id.js +5 -0
- package/dist/util/id.js.map +1 -0
- package/dist/util/logger.d.ts +3 -0
- package/dist/util/logger.d.ts.map +1 -0
- package/dist/util/logger.js +13 -0
- package/dist/util/logger.js.map +1 -0
- package/dist/util/pid.d.ts +2 -0
- package/dist/util/pid.d.ts.map +1 -0
- package/dist/util/pid.js +10 -0
- package/dist/util/pid.js.map +1 -0
- package/hooks/permission-hook.sh +116 -0
- package/package.json +59 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-task.js","sourceRoot":"","sources":["../../src/tools/update-task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,eAAgC;IACpF,MAAM,CAAC,IAAI,CACT,aAAa,EACb,8HAA8H,EAC9H;QACE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;QAC3D,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oFAAoF,CAAC;QAClH,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;KACjG,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE;QACpC,IAAI,CAAC;YACH,MAAM,eAAe,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;YAE1D,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;qBAChD;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACrE,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,0BAA0B,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;gBAC1G,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { MessageStore } from '../stores/message-store.js';
|
|
3
|
+
export declare function registerWaitForMessages(server: McpServer, messageStore: MessageStore): void;
|
|
4
|
+
//# sourceMappingURL=wait-for-messages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait-for-messages.d.ts","sourceRoot":"","sources":["../../src/tools/wait-for-messages.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAM/D,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,GAAG,IAAI,CA4C3F"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
3
|
+
const MAX_TIMEOUT_MS = 600_000;
|
|
4
|
+
export function registerWaitForMessages(server, messageStore) {
|
|
5
|
+
server.tool('wait_for_messages', 'Wait for the next message in your current room. Blocks until a message arrives or timeout.', {
|
|
6
|
+
timeoutMs: z.number().optional().describe('How long to wait in milliseconds (default: 30000, max: 600000). Returns a timeout result if no message arrives.'),
|
|
7
|
+
broadcastCooldownMs: z.number().optional().describe('Delay in ms before returning broadcast messages (not direct @mentions). Used to stagger responses across agents so earlier responders can be seen by later ones. Set this to a random value (0-3000) seeded at init time.'),
|
|
8
|
+
}, async ({ timeoutMs, broadcastCooldownMs }) => {
|
|
9
|
+
try {
|
|
10
|
+
const timeout = Math.min(timeoutMs ?? DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS);
|
|
11
|
+
// Check for unread messages first — return immediately if any exist
|
|
12
|
+
const existing = messageStore.getAll({ unreadOnly: true, limit: 1 });
|
|
13
|
+
if (existing.length > 0) {
|
|
14
|
+
messageStore.markAsRead([existing[0].messageId]);
|
|
15
|
+
return buildResponse(existing[0], broadcastCooldownMs, messageStore);
|
|
16
|
+
}
|
|
17
|
+
// Block until a message arrives or timeout
|
|
18
|
+
const message = await messageStore.waitForNext(timeout);
|
|
19
|
+
if (!message) {
|
|
20
|
+
return {
|
|
21
|
+
content: [
|
|
22
|
+
{
|
|
23
|
+
type: 'text',
|
|
24
|
+
text: JSON.stringify({ received: false, reason: 'timeout' }),
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
messageStore.markAsRead([message.messageId]);
|
|
30
|
+
return buildResponse(message, broadcastCooldownMs, messageStore);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
34
|
+
return {
|
|
35
|
+
content: [{ type: 'text', text: JSON.stringify({ error: `Failed to wait for messages: ${message}` }) }],
|
|
36
|
+
isError: true,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Build the response for a received message, applying broadcast cooldown if configured.
|
|
43
|
+
* Direct @mentions bypass the cooldown entirely.
|
|
44
|
+
* For broadcast messages, waits the cooldown period then gathers any messages
|
|
45
|
+
* that arrived during the wait as recentContext.
|
|
46
|
+
*/
|
|
47
|
+
async function buildResponse(message, broadcastCooldownMs, messageStore) {
|
|
48
|
+
const isDirect = message.mentionType === 'direct';
|
|
49
|
+
// Direct mentions or no cooldown configured — return immediately
|
|
50
|
+
if (isDirect || !broadcastCooldownMs || broadcastCooldownMs <= 0) {
|
|
51
|
+
return {
|
|
52
|
+
content: [
|
|
53
|
+
{
|
|
54
|
+
type: 'text',
|
|
55
|
+
text: JSON.stringify({
|
|
56
|
+
received: true,
|
|
57
|
+
message,
|
|
58
|
+
}, null, 2),
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// Broadcast message with cooldown — wait, then gather context
|
|
64
|
+
await new Promise((resolve) => setTimeout(resolve, broadcastCooldownMs));
|
|
65
|
+
// Collect any messages that arrived during the cooldown (responses from other agents)
|
|
66
|
+
const recentMessages = messageStore.getAll({ unreadOnly: true });
|
|
67
|
+
if (recentMessages.length > 0) {
|
|
68
|
+
messageStore.markAsRead(recentMessages.map((m) => m.messageId));
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
content: [
|
|
72
|
+
{
|
|
73
|
+
type: 'text',
|
|
74
|
+
text: JSON.stringify({
|
|
75
|
+
received: true,
|
|
76
|
+
message,
|
|
77
|
+
recentContext: recentMessages.length > 0 ? recentMessages : undefined,
|
|
78
|
+
cooldownApplied: broadcastCooldownMs,
|
|
79
|
+
}, null, 2),
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=wait-for-messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait-for-messages.js","sourceRoot":"","sources":["../../src/tools/wait-for-messages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PeerJsonRpcRequest, PeerJsonRpcResponse } from '../types.js';
|
|
2
|
+
export declare function createRequest(method: string, params?: Record<string, unknown>): PeerJsonRpcRequest;
|
|
3
|
+
export declare function createResponse(id: string | number, result: unknown): PeerJsonRpcResponse;
|
|
4
|
+
export declare function createErrorResponse(id: string | number, code: number, message: string, data?: unknown): PeerJsonRpcResponse;
|
|
5
|
+
export declare function encodeMessage(msg: PeerJsonRpcRequest | PeerJsonRpcResponse): Buffer;
|
|
6
|
+
export declare function decodeMessage(line: string): PeerJsonRpcRequest | PeerJsonRpcResponse;
|
|
7
|
+
//# sourceMappingURL=peer-protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-protocol.d.ts","sourceRoot":"","sources":["../../src/transport/peer-protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAG3E,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,kBAAkB,CAOlG;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,mBAAmB,CAMxF;AAED,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,MAAM,GAAG,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,OAAO,GACb,mBAAmB,CAMrB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,kBAAkB,GAAG,mBAAmB,GAAG,MAAM,CAEnF;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,mBAAmB,CAEpF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { generateId } from '../util/id.js';
|
|
2
|
+
export function createRequest(method, params) {
|
|
3
|
+
return {
|
|
4
|
+
jsonrpc: '2.0',
|
|
5
|
+
id: generateId(),
|
|
6
|
+
method,
|
|
7
|
+
params,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export function createResponse(id, result) {
|
|
11
|
+
return {
|
|
12
|
+
jsonrpc: '2.0',
|
|
13
|
+
id,
|
|
14
|
+
result,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function createErrorResponse(id, code, message, data) {
|
|
18
|
+
return {
|
|
19
|
+
jsonrpc: '2.0',
|
|
20
|
+
id,
|
|
21
|
+
error: { code, message, data },
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function encodeMessage(msg) {
|
|
25
|
+
return Buffer.from(JSON.stringify(msg) + '\n', 'utf-8');
|
|
26
|
+
}
|
|
27
|
+
export function decodeMessage(line) {
|
|
28
|
+
return JSON.parse(line.trim());
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=peer-protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-protocol.js","sourceRoot":"","sources":["../../src/transport/peer-protocol.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,MAAgC;IAC5E,OAAO;QACL,OAAO,EAAE,KAAK;QACd,EAAE,EAAE,UAAU,EAAE;QAChB,MAAM;QACN,MAAM;KACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAmB,EAAE,MAAe;IACjE,OAAO;QACL,OAAO,EAAE,KAAK;QACd,EAAE;QACF,MAAM;KACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,EAAmB,EACnB,IAAY,EACZ,OAAe,EACf,IAAc;IAEd,OAAO;QACL,OAAO,EAAE,KAAK;QACd,EAAE;QACF,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;KAC/B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAA6C;IACzE,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uds-client.d.ts","sourceRoot":"","sources":["../../src/transport/uds-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAMvD,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,SAAS,GAAE,MAA2B,GACrC,OAAO,CAAC,mBAAmB,CAAC,CAuD9B"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import net from 'node:net';
|
|
2
|
+
import { createRequest, encodeMessage } from './peer-protocol.js';
|
|
3
|
+
import { logError } from '../util/logger.js';
|
|
4
|
+
const DEFAULT_TIMEOUT_MS = 5000;
|
|
5
|
+
export async function sendPeerRequest(socketPath, method, params, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
6
|
+
return new Promise((resolve, reject) => {
|
|
7
|
+
const request = createRequest(method, params);
|
|
8
|
+
const socket = net.createConnection({ path: socketPath });
|
|
9
|
+
let responseData = '';
|
|
10
|
+
let settled = false;
|
|
11
|
+
const timer = setTimeout(() => {
|
|
12
|
+
if (!settled) {
|
|
13
|
+
settled = true;
|
|
14
|
+
socket.destroy();
|
|
15
|
+
reject(new Error(`Peer request timed out after ${timeoutMs}ms`));
|
|
16
|
+
}
|
|
17
|
+
}, timeoutMs);
|
|
18
|
+
socket.on('connect', () => {
|
|
19
|
+
socket.write(encodeMessage(request));
|
|
20
|
+
});
|
|
21
|
+
socket.on('data', (chunk) => {
|
|
22
|
+
responseData += chunk.toString('utf-8');
|
|
23
|
+
const newlineIdx = responseData.indexOf('\n');
|
|
24
|
+
if (newlineIdx !== -1) {
|
|
25
|
+
const line = responseData.slice(0, newlineIdx);
|
|
26
|
+
if (!settled) {
|
|
27
|
+
settled = true;
|
|
28
|
+
clearTimeout(timer);
|
|
29
|
+
try {
|
|
30
|
+
const response = JSON.parse(line);
|
|
31
|
+
resolve(response);
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
reject(new Error('Invalid JSON response from peer'));
|
|
35
|
+
}
|
|
36
|
+
socket.end();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
socket.on('error', (err) => {
|
|
41
|
+
if (!settled) {
|
|
42
|
+
settled = true;
|
|
43
|
+
clearTimeout(timer);
|
|
44
|
+
logError(`Peer connection error (${socketPath})`, err);
|
|
45
|
+
reject(err);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
socket.on('close', () => {
|
|
49
|
+
if (!settled) {
|
|
50
|
+
settled = true;
|
|
51
|
+
clearTimeout(timer);
|
|
52
|
+
reject(new Error('Connection closed before response'));
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=uds-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uds-client.js","sourceRoot":"","sources":["../../src/transport/uds-client.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,UAAU,CAAC;AAE3B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,UAAkB,EAClB,MAAc,EACd,MAAgC,EAChC,YAAoB,kBAAkB;IAEtC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,GAAG,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;QAC1D,IAAI,YAAY,GAAG,EAAE,CAAC;QACtB,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,GAAG,IAAI,CAAC;gBACf,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjB,MAAM,CAAC,IAAI,KAAK,CAAC,gCAAgC,SAAS,IAAI,CAAC,CAAC,CAAC;YACnE,CAAC;QACH,CAAC,EAAE,SAAS,CAAC,CAAC;QAEd,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YACxB,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,YAAY,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACxC,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC9C,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;gBACtB,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;gBAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,OAAO,GAAG,IAAI,CAAC;oBACf,YAAY,CAAC,KAAK,CAAC,CAAC;oBACpB,IAAI,CAAC;wBACH,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAwB,CAAC;wBACzD,OAAO,CAAC,QAAQ,CAAC,CAAC;oBACpB,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,MAAM,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;oBACvD,CAAC;oBACD,MAAM,CAAC,GAAG,EAAE,CAAC;gBACf,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;YAChD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,GAAG,IAAI,CAAC;gBACf,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,QAAQ,CAAC,0BAA0B,UAAU,GAAG,EAAE,GAAG,CAAC,CAAC;gBACvD,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACtB,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,GAAG,IAAI,CAAC;gBACf,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,MAAM,CAAC,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAC;YACzD,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type RequestHandler = (method: string, params: Record<string, unknown> | undefined) => Promise<unknown>;
|
|
2
|
+
export declare class UdsServer {
|
|
3
|
+
private server;
|
|
4
|
+
private socketPath;
|
|
5
|
+
private handler;
|
|
6
|
+
constructor(socketPath: string, handler: RequestHandler);
|
|
7
|
+
start(): Promise<void>;
|
|
8
|
+
private handleConnection;
|
|
9
|
+
private processRequest;
|
|
10
|
+
close(): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=uds-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uds-server.d.ts","sourceRoot":"","sources":["../../src/transport/uds-server.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,cAAc,GAAG,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,KACxC,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAiB;gBAEpB,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc;IAKjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB5B,OAAO,CAAC,gBAAgB;YAkBV,cAAc;IAwBtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAY7B"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import net from 'node:net';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import { createResponse, createErrorResponse, encodeMessage } from './peer-protocol.js';
|
|
4
|
+
import { log, logError } from '../util/logger.js';
|
|
5
|
+
export class UdsServer {
|
|
6
|
+
server = null;
|
|
7
|
+
socketPath;
|
|
8
|
+
handler;
|
|
9
|
+
constructor(socketPath, handler) {
|
|
10
|
+
this.socketPath = socketPath;
|
|
11
|
+
this.handler = handler;
|
|
12
|
+
}
|
|
13
|
+
async start() {
|
|
14
|
+
// Clean up any existing socket file
|
|
15
|
+
try {
|
|
16
|
+
await fs.unlink(this.socketPath);
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
if (err.code !== 'ENOENT')
|
|
20
|
+
throw err;
|
|
21
|
+
}
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
this.server = net.createServer((socket) => {
|
|
24
|
+
this.handleConnection(socket);
|
|
25
|
+
});
|
|
26
|
+
this.server.on('error', (err) => {
|
|
27
|
+
logError('UDS server error', err);
|
|
28
|
+
reject(err);
|
|
29
|
+
});
|
|
30
|
+
this.server.listen(this.socketPath, () => {
|
|
31
|
+
log(`UDS server listening on ${this.socketPath}`);
|
|
32
|
+
resolve();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
handleConnection(socket) {
|
|
37
|
+
let buffer = '';
|
|
38
|
+
socket.on('data', (chunk) => {
|
|
39
|
+
buffer += chunk.toString('utf-8');
|
|
40
|
+
const newlineIdx = buffer.indexOf('\n');
|
|
41
|
+
if (newlineIdx !== -1) {
|
|
42
|
+
const line = buffer.slice(0, newlineIdx);
|
|
43
|
+
buffer = buffer.slice(newlineIdx + 1);
|
|
44
|
+
this.processRequest(line, socket);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
socket.on('error', (err) => {
|
|
48
|
+
logError('UDS connection error', err);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async processRequest(line, socket) {
|
|
52
|
+
let request;
|
|
53
|
+
try {
|
|
54
|
+
request = JSON.parse(line);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
const errResp = createErrorResponse(0, -32700, 'Parse error');
|
|
58
|
+
socket.write(encodeMessage(errResp));
|
|
59
|
+
socket.end();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
let response;
|
|
63
|
+
try {
|
|
64
|
+
const result = await this.handler(request.method, request.params);
|
|
65
|
+
response = createResponse(request.id, result);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const message = err instanceof Error ? err.message : 'Internal error';
|
|
69
|
+
response = createErrorResponse(request.id, -32603, message);
|
|
70
|
+
}
|
|
71
|
+
socket.write(encodeMessage(response));
|
|
72
|
+
socket.end();
|
|
73
|
+
}
|
|
74
|
+
async close() {
|
|
75
|
+
return new Promise((resolve) => {
|
|
76
|
+
if (!this.server) {
|
|
77
|
+
resolve();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
this.server.close(() => {
|
|
81
|
+
log('UDS server closed');
|
|
82
|
+
resolve();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=uds-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uds-server.js","sourceRoot":"","sources":["../../src/transport/uds-server.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type MessageImportance = 'important' | 'comment' | 'chitchat';
|
|
2
|
+
export interface PeerMessage {
|
|
3
|
+
messageId: string;
|
|
4
|
+
fromPeerId: string;
|
|
5
|
+
fromName: string;
|
|
6
|
+
content: string;
|
|
7
|
+
metadata?: Record<string, unknown>;
|
|
8
|
+
sentAt: string;
|
|
9
|
+
receivedAt: string;
|
|
10
|
+
read: boolean;
|
|
11
|
+
relatedTaskId?: string;
|
|
12
|
+
replyToMessageId?: string;
|
|
13
|
+
type?: 'message' | 'task_result' | 'task_delegated';
|
|
14
|
+
mentions?: string[];
|
|
15
|
+
mentionType?: 'direct' | 'here' | 'broadcast';
|
|
16
|
+
importance?: MessageImportance;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;AAErE,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,SAAS,GAAG,aAAa,GAAG,gBAAgB,CAAC;IACpD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IAC9C,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAChC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,mBAAmB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../src/util/id.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
|
package/dist/util/id.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id.js","sourceRoot":"","sources":["../../src/util/id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,UAAU,UAAU;IACxB,OAAO,UAAU,EAAE,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/util/logger.ts"],"names":[],"mappings":"AAEA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAE7D;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI,CAM/D"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const PREFIX = '[crosschat]';
|
|
2
|
+
export function log(message, ...args) {
|
|
3
|
+
console.error(`${PREFIX} ${message}`, ...args);
|
|
4
|
+
}
|
|
5
|
+
export function logError(message, error) {
|
|
6
|
+
if (error instanceof Error) {
|
|
7
|
+
console.error(`${PREFIX} ERROR: ${message}:`, error.message);
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
console.error(`${PREFIX} ERROR: ${message}`, error ?? '');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/util/logger.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,aAAa,CAAC;AAE7B,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,GAAG,IAAe;IACrD,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAe,EAAE,KAAe;IACvD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,WAAW,OAAO,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/D,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,WAAW,OAAO,EAAE,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pid.d.ts","sourceRoot":"","sources":["../../src/util/pid.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOnD"}
|
package/dist/util/pid.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pid.js","sourceRoot":"","sources":["../../src/util/pid.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# CrossChat Permission Hook for Claude Code
|
|
3
|
+
#
|
|
4
|
+
# Elevates Claude Code permission requests to the CrossChat dashboard.
|
|
5
|
+
# The script POSTs the request to the hub, then polls until the user
|
|
6
|
+
# approves or denies it from the dashboard UI.
|
|
7
|
+
#
|
|
8
|
+
# Setup — add to your Claude Code settings (~/.claude/settings.json):
|
|
9
|
+
#
|
|
10
|
+
# "hooks": {
|
|
11
|
+
# "PreToolUse": [{
|
|
12
|
+
# "matcher": "",
|
|
13
|
+
# "hooks": [{
|
|
14
|
+
# "type": "command",
|
|
15
|
+
# "command": "/path/to/crosschat/hooks/permission-hook.sh",
|
|
16
|
+
# "timeout": 300
|
|
17
|
+
# }]
|
|
18
|
+
# }]
|
|
19
|
+
# }
|
|
20
|
+
#
|
|
21
|
+
# Requires: curl, jq
|
|
22
|
+
# Env: CROSSCHAT_HUB_URL (default: auto-detected from ~/.crosschat/dashboard.lock)
|
|
23
|
+
|
|
24
|
+
set -euo pipefail
|
|
25
|
+
|
|
26
|
+
# ── Opt-in gate — only crosschat-connected sessions trigger this ──
|
|
27
|
+
|
|
28
|
+
if [ -n "${CROSSCHAT_AGENT_NAME:-}" ]; then
|
|
29
|
+
AGENT_NAME="$CROSSCHAT_AGENT_NAME"
|
|
30
|
+
elif [ -f "$HOME/.crosschat/sessions/$PPID" ]; then
|
|
31
|
+
# MCP-connected instance — read agent name from session marker
|
|
32
|
+
AGENT_NAME=$(jq -r '.name // empty' "$HOME/.crosschat/sessions/$PPID" 2>/dev/null)
|
|
33
|
+
if [ -z "$AGENT_NAME" ]; then
|
|
34
|
+
exit 0 # Marker exists but unreadable — fall through
|
|
35
|
+
fi
|
|
36
|
+
else
|
|
37
|
+
exit 0 # Not a crosschat agent — fall through to normal permissions
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# ── Resolve hub URL ───────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
LOCK_FILE="$HOME/.crosschat/dashboard.lock"
|
|
43
|
+
|
|
44
|
+
if [ -n "${CROSSCHAT_HUB_URL:-}" ]; then
|
|
45
|
+
HUB_URL="$CROSSCHAT_HUB_URL"
|
|
46
|
+
elif [ -f "$LOCK_FILE" ]; then
|
|
47
|
+
PORT=$(jq -r '.port' "$LOCK_FILE" 2>/dev/null)
|
|
48
|
+
if [ -n "$PORT" ] && [ "$PORT" != "null" ]; then
|
|
49
|
+
HUB_URL="http://localhost:${PORT}"
|
|
50
|
+
else
|
|
51
|
+
exit 0 # No hub running — fall through to normal permissions
|
|
52
|
+
fi
|
|
53
|
+
else
|
|
54
|
+
exit 0 # No lock file — fall through to normal permissions
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# ── Read hook input from stdin ────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
INPUT=$(cat)
|
|
60
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
|
|
61
|
+
|
|
62
|
+
# Skip if no tool name
|
|
63
|
+
if [ -z "$TOOL_NAME" ]; then
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
TOOL_INPUT=$(echo "$INPUT" | jq -c '.tool_input // {}')
|
|
68
|
+
DESCRIPTION=$(echo "$INPUT" | jq -r '.tool_input.description // empty')
|
|
69
|
+
|
|
70
|
+
# ── POST permission request to hub ────────────────────────────────
|
|
71
|
+
|
|
72
|
+
RESPONSE=$(curl -s -X POST "${HUB_URL}/api/permissions" \
|
|
73
|
+
-H "Content-Type: application/json" \
|
|
74
|
+
-d "$(jq -n \
|
|
75
|
+
--arg agentName "$AGENT_NAME" \
|
|
76
|
+
--arg toolName "$TOOL_NAME" \
|
|
77
|
+
--argjson toolInput "$TOOL_INPUT" \
|
|
78
|
+
--arg description "$DESCRIPTION" \
|
|
79
|
+
'{agentName: $agentName, toolName: $toolName, toolInput: $toolInput, description: $description}'
|
|
80
|
+
)" 2>/dev/null) || exit 0
|
|
81
|
+
|
|
82
|
+
PERM_ID=$(echo "$RESPONSE" | jq -r '.id // empty')
|
|
83
|
+
if [ -z "$PERM_ID" ]; then
|
|
84
|
+
exit 0 # Failed to create — fall through to normal permissions
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# ── Poll for decision ─────────────────────────────────────────────
|
|
88
|
+
|
|
89
|
+
MAX_WAIT=300 # 5 minutes
|
|
90
|
+
ELAPSED=0
|
|
91
|
+
INTERVAL=1
|
|
92
|
+
|
|
93
|
+
while [ $ELAPSED -lt $MAX_WAIT ]; do
|
|
94
|
+
RESULT=$(curl -s "${HUB_URL}/api/permissions/${PERM_ID}" 2>/dev/null) || break
|
|
95
|
+
STATUS=$(echo "$RESULT" | jq -r '.status // "pending"')
|
|
96
|
+
|
|
97
|
+
if [ "$STATUS" = "approved" ]; then
|
|
98
|
+
# Return allow decision
|
|
99
|
+
cat <<ALLOW_EOF
|
|
100
|
+
{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"Approved via CrossChat dashboard"}}
|
|
101
|
+
ALLOW_EOF
|
|
102
|
+
exit 0
|
|
103
|
+
elif [ "$STATUS" = "denied" ]; then
|
|
104
|
+
REASON=$(echo "$RESULT" | jq -r '.reason // "Denied via CrossChat dashboard"')
|
|
105
|
+
# Return deny decision (use jq to safely encode the reason into JSON)
|
|
106
|
+
jq -n --arg reason "$REASON" \
|
|
107
|
+
'{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":$reason}}'
|
|
108
|
+
exit 0
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
sleep $INTERVAL
|
|
112
|
+
ELAPSED=$((ELAPSED + INTERVAL))
|
|
113
|
+
done
|
|
114
|
+
|
|
115
|
+
# Timed out — allow by default
|
|
116
|
+
exit 0
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@studiomopoke/crosschat",
|
|
3
|
+
"version": "1.6.0",
|
|
4
|
+
"description": "MCP server for inter-instance Claude Code communication",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"crosschat": "bin/cli.cjs"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin/",
|
|
12
|
+
"dist/",
|
|
13
|
+
"hooks/",
|
|
14
|
+
"dashboard/dist/",
|
|
15
|
+
"crosschat.md",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"build:dashboard": "cd dashboard && npm install && npm run build",
|
|
22
|
+
"build:all": "npm run build && npm run build:dashboard",
|
|
23
|
+
"prepublishOnly": "npm run build:all",
|
|
24
|
+
"start": "node dist/index.js",
|
|
25
|
+
"dev": "tsx src/index.ts"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"claude",
|
|
29
|
+
"claude-code",
|
|
30
|
+
"mcp",
|
|
31
|
+
"ai",
|
|
32
|
+
"agentic",
|
|
33
|
+
"collaboration",
|
|
34
|
+
"inter-instance",
|
|
35
|
+
"crosschat"
|
|
36
|
+
],
|
|
37
|
+
"author": "StudioMopoke",
|
|
38
|
+
"license": "BUSL-1.1",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/StudioMopoke/crosschat"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
45
|
+
"express": "^5.2.1",
|
|
46
|
+
"ws": "^8.19.0",
|
|
47
|
+
"zod": "^3.25.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/express": "^5.0.6",
|
|
51
|
+
"@types/node": "^22.0.0",
|
|
52
|
+
"@types/ws": "^8.18.1",
|
|
53
|
+
"tsx": "^4.19.0",
|
|
54
|
+
"typescript": "^5.8.0"
|
|
55
|
+
},
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=20.0.0"
|
|
58
|
+
}
|
|
59
|
+
}
|