@sleep2agi/commhub-server 0.8.3 → 0.8.4-preview.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/package.json +1 -1
- package/src/index.ts +5 -5
- package/src/tools.ts +9 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sleep2agi/commhub-server",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.4-preview.0",
|
|
4
4
|
"description": "CommHub Server — AI Agent communication hub with MCP protocol, multi-network isolation, user auth, and 17 MCP tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
package/src/index.ts
CHANGED
|
@@ -80,12 +80,12 @@ setInterval(() => {
|
|
|
80
80
|
}, 300000);
|
|
81
81
|
|
|
82
82
|
// ── Factory: 每个请求创建新的 McpServer(stateless 模式)──
|
|
83
|
-
function createServer(clientIP?: string, enforceNetworkId?: string | null, enforceUserId?: string | null, callerAlias?: string | null, callerTokenIsNetwork = false): McpServer {
|
|
83
|
+
function createServer(clientIP?: string, enforceNetworkId?: string | null, enforceUserId?: string | null, callerAlias?: string | null, callerTokenIsNetwork = false, callerTokenId?: string | null): McpServer {
|
|
84
84
|
const server = new McpServer({
|
|
85
85
|
name: "commhub",
|
|
86
86
|
version: "0.5.0",
|
|
87
87
|
});
|
|
88
|
-
registerTools(server, clientIP, enforceNetworkId, enforceUserId, callerAlias, callerTokenIsNetwork);
|
|
88
|
+
registerTools(server, clientIP, enforceNetworkId, enforceUserId, callerAlias, callerTokenIsNetwork, callerTokenId);
|
|
89
89
|
return server;
|
|
90
90
|
}
|
|
91
91
|
|
|
@@ -170,12 +170,12 @@ function requireTmuxAccess(req: Request, server?: any): Response | null {
|
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
// Extract user + network + token-binding identity from request token.
|
|
173
|
-
function resolveRequestAuth(req: Request): { userId: string; networkId: string | null; username: string; tokenName: string | null } | null {
|
|
173
|
+
function resolveRequestAuth(req: Request): { userId: string; networkId: string | null; username: string; tokenName: string | null; tokenId: string | null } | null {
|
|
174
174
|
const token = requestToken(req);
|
|
175
175
|
if (!token) return null;
|
|
176
176
|
const resolved = resolveToken(token);
|
|
177
177
|
if (!resolved) return null;
|
|
178
|
-
return { userId: resolved.user.user_id, networkId: resolved.networkId, username: resolved.user.username, tokenName: resolved.tokenName };
|
|
178
|
+
return { userId: resolved.user.user_id, networkId: resolved.networkId, username: resolved.user.username, tokenName: resolved.tokenName, tokenId: resolved.tokenId };
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
type RestNetworkScope = {
|
|
@@ -449,7 +449,7 @@ Bun.serve({
|
|
|
449
449
|
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
450
450
|
sessionIdGenerator: undefined,
|
|
451
451
|
});
|
|
452
|
-
const mcpServer = createServer(clientIP, enforceNetId, authCtx?.userId || null, callerAlias, !!token?.startsWith("ntok_"));
|
|
452
|
+
const mcpServer = createServer(clientIP, enforceNetId, authCtx?.userId || null, callerAlias, !!token?.startsWith("ntok_"), authCtx?.tokenId || null);
|
|
453
453
|
await mcpServer.connect(transport);
|
|
454
454
|
const response = await transport.handleRequest(req);
|
|
455
455
|
// Disconnect after response to prevent McpServer leak
|
package/src/tools.ts
CHANGED
|
@@ -19,13 +19,13 @@ function normalizeMetaJson(meta: unknown): string | null {
|
|
|
19
19
|
try { return JSON.stringify(meta); } catch { return null; }
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export function registerTools(server: McpServer, clientIP?: string, enforceNetworkId?: string | null, enforceUserId?: string | null, callerAlias?: string | null, callerTokenIsNetwork = false) {
|
|
22
|
+
export function registerTools(server: McpServer, clientIP?: string, enforceNetworkId?: string | null, enforceUserId?: string | null, callerAlias?: string | null, callerTokenIsNetwork = false, callerTokenId?: string | null) {
|
|
23
23
|
// Default from_session for outbound tools — extracted from the calling
|
|
24
24
|
// token's binding (ntok_ → node alias, utok_ → username). Without this,
|
|
25
25
|
// an agent's send_task call always claimed from='hub' and peer agents
|
|
26
|
-
// couldn't tell who actually asked them.
|
|
27
|
-
//
|
|
28
|
-
const defaultFrom = (clientFrom?: string) => clientFrom || callerAlias || "hub";
|
|
26
|
+
// couldn't tell who actually asked them. Network-bound node tokens are an
|
|
27
|
+
// identity boundary: they must not spoof another node via from_session.
|
|
28
|
+
const defaultFrom = (clientFrom?: string) => (callerTokenIsNetwork && callerAlias) ? callerAlias : (clientFrom || callerAlias || "hub");
|
|
29
29
|
// If enforceNetworkId is set, override any client-supplied network_id
|
|
30
30
|
const getNetworkId = (clientNetId?: string | null) => enforceNetworkId ?? clientNetId ?? null;
|
|
31
31
|
|
|
@@ -190,6 +190,11 @@ export function registerTools(server: McpServer, clientIP?: string, enforceNetwo
|
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
192
|
console.log(`[${ts()}] ${effectiveAlias} (${resume_id.slice(0, 8)}) → report_status: ${status}${task ? " | " + task.slice(0, 60) : ""}${effectiveNetId ? " [net]" : ""}${canonical.renamed ? ` [renamed from ${alias}]` : ""}`);
|
|
193
|
+
if (callerTokenIsNetwork && callerTokenId) {
|
|
194
|
+
try {
|
|
195
|
+
db.run("UPDATE api_tokens SET name = ?1 WHERE token_id = ?2", [`node:${effectiveAlias}`, callerTokenId]);
|
|
196
|
+
} catch {}
|
|
197
|
+
}
|
|
193
198
|
const trimmedOutput = output?.slice(0, 4000);
|
|
194
199
|
const hostHostname = host?.hostname || hn || null;
|
|
195
200
|
const hostIp = host?.ip || clientIP || null;
|