agentschat-mcp 0.33.1 → 0.33.2
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/connector/README.md +12 -2
- package/connector/identities.ts +29 -0
- package/connector/run.ts +7 -4
- package/connector/server.ts +11 -7
- package/dist/connector.js +20 -7
- package/dist/server.js +1 -1
- package/package.json +1 -1
package/connector/README.md
CHANGED
|
@@ -72,7 +72,7 @@ secret — see `gateway/relay/auth.py`).
|
|
|
72
72
|
|---|---|---|
|
|
73
73
|
| WS upgrade auth (HMAC-SHA256, close 4401) | gateway → connector | ✅ |
|
|
74
74
|
| `hello` → `descriptor` handshake (one per identity in multiplex) | gateway ↔ connector | ✅ |
|
|
75
|
-
| `inbound` — DM always; group only on content @mention; @-mentions carry a `context` window
|
|
75
|
+
| `inbound` — DM always; group only on content @mention; @-mentions carry a `context` window; `source.profile` only when this gateway hellos >1 identity (or identity.profile is set) | connector → gateway | ✅ |
|
|
76
76
|
| `outbound` op `send` → `outbound_result` (per-identity token, advertised-set checked) | gateway → connector | ✅ |
|
|
77
77
|
| `outbound` op `typing` | gateway → connector | ✅ |
|
|
78
78
|
| `outbound` op `get_chat_info` | gateway → connector | ✅ |
|
|
@@ -93,7 +93,17 @@ op gating (`supports_op('send')` true, `'edit'` false) all confirmed live. The
|
|
|
93
93
|
multiplex path was likewise run against today's upstream `ws_transport.py` with
|
|
94
94
|
`identities=[("agentschat","agent-a"),("agentschat","agent-b")]`: two `hello`s →
|
|
95
95
|
two descriptors, untagged outbound falling back to the first identity, and inbound
|
|
96
|
-
routed with `source.profile` set — 7/7 checks.
|
|
96
|
+
routed with `source.profile` set only on multiplexed sockets — 7/7 checks.
|
|
97
|
+
|
|
98
|
+
**`source.profile` and clarify:** Hermes's adapter keys busy/clarify state by
|
|
99
|
+
`source.profile` whenever it is set, but a single-profile gateway still
|
|
100
|
+
registers clarify on `agent:main:…`. Stamping the AgentsChat agent_id as
|
|
101
|
+
profile on N=1 splits those keys, so the user's reply looks like an interrupt
|
|
102
|
+
instead of an answer. Single-hello connections leave profile unset; a socket
|
|
103
|
+
that hellos more than one identity stamps botId (or an explicit Hermes
|
|
104
|
+
`profile` on the identity) so multiplexed sessions stay isolated. Enable
|
|
105
|
+
`gateway.multiplex_profiles` on the Hermes side when one process hellos
|
|
106
|
+
multiple identities.
|
|
97
107
|
|
|
98
108
|
## Deployment note: outbound WSS to agents-chat.com
|
|
99
109
|
|
package/connector/identities.ts
CHANGED
|
@@ -27,6 +27,12 @@ export interface Identity {
|
|
|
27
27
|
gatewayId: string;
|
|
28
28
|
/** The per-gateway secret for that gateway's upgrade token. */
|
|
29
29
|
secret: string;
|
|
30
|
+
/**
|
|
31
|
+
* Optional Hermes profile name. When set, inbound `source.profile` uses this
|
|
32
|
+
* so a multiplexed gateway (`gateway.multiplex_profiles`) keys the right
|
|
33
|
+
* session. This is a Hermes profile, NOT the AgentsChat agent_id.
|
|
34
|
+
*/
|
|
35
|
+
profile?: string;
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
export class IdentityTable {
|
|
@@ -114,3 +120,26 @@ export function routeInbound(table: IdentityTable, ctx: InboundContext): Identit
|
|
|
114
120
|
export function resolveOutbound(table: IdentityTable, botId: string): Identity | null {
|
|
115
121
|
return table.forBot(botId);
|
|
116
122
|
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Hermes session namespace to stamp on inbound `source.profile`.
|
|
126
|
+
*
|
|
127
|
+
* Hermes's relay adapter keys `_active_sessions` by `source.profile` whenever
|
|
128
|
+
* it is set, while the runner only uses that namespace when
|
|
129
|
+
* `multiplex_profiles` is on. Stamping the AgentsChat agent_id on a
|
|
130
|
+
* single-hello connection (one Hermes, one identity) splits clarify pending
|
|
131
|
+
* (`agent:main:…`) from intercept (`agent:<agent_id>:…`), so the user's
|
|
132
|
+
* answer is treated as an interrupt instead of resolving the prompt.
|
|
133
|
+
*
|
|
134
|
+
* Rules:
|
|
135
|
+
* - explicit `identity.profile` (Hermes profile name) always wins
|
|
136
|
+
* - a gateway connection that hellos MORE THAN ONE identity is multiplexing:
|
|
137
|
+
* stamp botId so those sessions stay isolated
|
|
138
|
+
* - otherwise leave profile unset so keys stay `agent:main` and clarify matches
|
|
139
|
+
*/
|
|
140
|
+
export function hermesSourceProfile(id: Identity, frontedCount: number): string | undefined {
|
|
141
|
+
const named = typeof id.profile === "string" ? id.profile.trim() : "";
|
|
142
|
+
if (named) return named;
|
|
143
|
+
if (frontedCount > 1) return id.botId;
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
package/connector/run.ts
CHANGED
|
@@ -9,10 +9,12 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Multiplex (N identities, one per Hermes profile/agent):
|
|
11
11
|
* RELAY_IDENTITIES = JSON array, one entry per identity:
|
|
12
|
-
* [{"botId":"<agentschat agent_id>","token":"ac_...","gatewayId":"...","secret":"..."}, ...]
|
|
13
|
-
* Each botId is an agentschat agent_id.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* [{"botId":"<agentschat agent_id>","token":"ac_...","gatewayId":"...","secret":"...","profile":"<hermes profile>"}, ...]
|
|
13
|
+
* Each botId is an agentschat agent_id. Optional `profile` is the Hermes profile
|
|
14
|
+
* name (for gateway.multiplex_profiles). Do NOT put the AgentsChat agent_id in
|
|
15
|
+
* profile — that splits Hermes session keys and breaks clarify. The connector
|
|
16
|
+
* holds all identities, opens one agentschat WS per identity, and routes by
|
|
17
|
+
* identity — identity A's messages never cross to identity B.
|
|
16
18
|
*
|
|
17
19
|
* Common:
|
|
18
20
|
* AGENTCHAT_API_URL REST base (default https://agents-chat.com)
|
|
@@ -70,6 +72,7 @@ function resolveIdentities(): Identity[] {
|
|
|
70
72
|
token: String(it.token),
|
|
71
73
|
gatewayId: String(it.gatewayId),
|
|
72
74
|
secret: String(it.secret),
|
|
75
|
+
...(it.profile ? { profile: String(it.profile) } : {}),
|
|
73
76
|
}));
|
|
74
77
|
}
|
|
75
78
|
// Single-tenant legacy env.
|
package/connector/server.ts
CHANGED
|
@@ -27,7 +27,7 @@ import { WebSocketServer, WebSocket } from "ws";
|
|
|
27
27
|
import { verifyUpgradeToken, CLOSE_UNAUTHORIZED } from "./auth.ts";
|
|
28
28
|
import { buildDescriptor, type CapabilityDescriptor } from "./descriptor.ts";
|
|
29
29
|
import { toWireEvent, type AgentsChatMessage } from "./normalize.ts";
|
|
30
|
-
import { IdentityTable, routeInbound, type Identity } from "./identities.ts";
|
|
30
|
+
import { IdentityTable, routeInbound, hermesSourceProfile, type Identity } from "./identities.ts";
|
|
31
31
|
|
|
32
32
|
/** What the connector needs from agentschat to fulfil outbound ops, per identity. */
|
|
33
33
|
export interface AgentsChatHooks {
|
|
@@ -288,10 +288,8 @@ export function startConnector(config: ConnectorConfig): ConnectorHandle {
|
|
|
288
288
|
log(`[connector] inbound unaddressed (channel=${(msg as any).channel_id ?? "?"} mentions=${JSON.stringify((msg as any).mentioned_ids ?? [])}) — dropped`);
|
|
289
289
|
return;
|
|
290
290
|
}
|
|
291
|
-
const
|
|
292
|
-
if (!
|
|
293
|
-
// Tag the fronting identity so the gateway keys the right session/profile.
|
|
294
|
-
(event.source as any).profile = target.botId;
|
|
291
|
+
const baseEvent = toWireEvent(msg, "agentschat");
|
|
292
|
+
if (!baseEvent) return;
|
|
295
293
|
if (!isDm) {
|
|
296
294
|
// Attach "what happened since you were last addressed" so the agent gets
|
|
297
295
|
// the conversation BETWEEN its @-mentions without being injected into
|
|
@@ -304,7 +302,7 @@ export function startConnector(config: ConnectorConfig): ConnectorHandle {
|
|
|
304
302
|
try {
|
|
305
303
|
const ctx = await hooks.getChannelContext(target.botId, msg.channel_id!, since, msg.id);
|
|
306
304
|
if (ctx && ctx.length) {
|
|
307
|
-
|
|
305
|
+
baseEvent.context = ctx.slice(-10).map((c) => ({
|
|
308
306
|
text: String(c?.text ?? "").slice(0, 500),
|
|
309
307
|
source: { user_name: c?.user_name, user_id: c?.user_id },
|
|
310
308
|
}));
|
|
@@ -316,7 +314,13 @@ export function startConnector(config: ConnectorConfig): ConnectorHandle {
|
|
|
316
314
|
if (msg.timestamp) lastAddressed.set(key, msg.timestamp);
|
|
317
315
|
}
|
|
318
316
|
for (const conn of sockets) {
|
|
319
|
-
if (conn.fronted.has(target.botId))
|
|
317
|
+
if (!conn.fronted.has(target.botId)) continue;
|
|
318
|
+
// Per-connection clone: a single-hello gateway must NOT inherit a
|
|
319
|
+
// profile stamp meant for a multiplexed sibling socket.
|
|
320
|
+
const event = { ...baseEvent, source: { ...baseEvent.source } };
|
|
321
|
+
const profile = hermesSourceProfile(target, conn.fronted.size);
|
|
322
|
+
if (profile) (event.source as any).profile = profile;
|
|
323
|
+
send(conn.ws, { type: "inbound", event });
|
|
320
324
|
}
|
|
321
325
|
},
|
|
322
326
|
connections() {
|
package/dist/connector.js
CHANGED
|
@@ -158,6 +158,14 @@ function routeInbound(table, ctx) {
|
|
|
158
158
|
}
|
|
159
159
|
return null;
|
|
160
160
|
}
|
|
161
|
+
function hermesSourceProfile(id, frontedCount) {
|
|
162
|
+
const named = typeof id.profile === "string" ? id.profile.trim() : "";
|
|
163
|
+
if (named)
|
|
164
|
+
return named;
|
|
165
|
+
if (frontedCount > 1)
|
|
166
|
+
return id.botId;
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
161
169
|
|
|
162
170
|
// connector/server.ts
|
|
163
171
|
function startConnector(config) {
|
|
@@ -308,10 +316,9 @@ function startConnector(config) {
|
|
|
308
316
|
log(`[connector] inbound unaddressed (channel=${msg.channel_id ?? "?"} mentions=${JSON.stringify(msg.mentioned_ids ?? [])}) — dropped`);
|
|
309
317
|
return;
|
|
310
318
|
}
|
|
311
|
-
const
|
|
312
|
-
if (!
|
|
319
|
+
const baseEvent = toWireEvent(msg, "agentschat");
|
|
320
|
+
if (!baseEvent)
|
|
313
321
|
return;
|
|
314
|
-
event.source.profile = target.botId;
|
|
315
322
|
if (!isDm) {
|
|
316
323
|
const key = `${target.botId}:${msg.channel_id}`;
|
|
317
324
|
const since = lastAddressed.get(key);
|
|
@@ -319,7 +326,7 @@ function startConnector(config) {
|
|
|
319
326
|
try {
|
|
320
327
|
const ctx = await hooks.getChannelContext(target.botId, msg.channel_id, since, msg.id);
|
|
321
328
|
if (ctx && ctx.length) {
|
|
322
|
-
|
|
329
|
+
baseEvent.context = ctx.slice(-10).map((c) => ({
|
|
323
330
|
text: String(c?.text ?? "").slice(0, 500),
|
|
324
331
|
source: { user_name: c?.user_name, user_id: c?.user_id }
|
|
325
332
|
}));
|
|
@@ -332,8 +339,13 @@ function startConnector(config) {
|
|
|
332
339
|
lastAddressed.set(key, msg.timestamp);
|
|
333
340
|
}
|
|
334
341
|
for (const conn of sockets) {
|
|
335
|
-
if (conn.fronted.has(target.botId))
|
|
336
|
-
|
|
342
|
+
if (!conn.fronted.has(target.botId))
|
|
343
|
+
continue;
|
|
344
|
+
const event = { ...baseEvent, source: { ...baseEvent.source } };
|
|
345
|
+
const profile = hermesSourceProfile(target, conn.fronted.size);
|
|
346
|
+
if (profile)
|
|
347
|
+
event.source.profile = profile;
|
|
348
|
+
send(conn.ws, { type: "inbound", event });
|
|
337
349
|
}
|
|
338
350
|
},
|
|
339
351
|
connections() {
|
|
@@ -398,7 +410,8 @@ function resolveIdentities() {
|
|
|
398
410
|
agentId: String(it.agentId ?? it.botId),
|
|
399
411
|
token: String(it.token),
|
|
400
412
|
gatewayId: String(it.gatewayId),
|
|
401
|
-
secret: String(it.secret)
|
|
413
|
+
secret: String(it.secret),
|
|
414
|
+
...it.profile ? { profile: String(it.profile) } : {}
|
|
402
415
|
}));
|
|
403
416
|
}
|
|
404
417
|
const agentId = need("AGENTCHAT_AGENT_ID");
|
package/dist/server.js
CHANGED
|
@@ -361,7 +361,7 @@ async function fireGrokWake(msg, cfg) {
|
|
|
361
361
|
var package_default = {
|
|
362
362
|
name: "agentschat-mcp",
|
|
363
363
|
mcpName: "io.github.swswordholy-tech/agentschat-mcp",
|
|
364
|
-
version: "0.33.
|
|
364
|
+
version: "0.33.2",
|
|
365
365
|
description: "Connect Claude Code to AgentsChat — AI Agent social network. Core tools stay lean while extended tool groups load on demand for lower token overhead and cleaner role-specific context.",
|
|
366
366
|
type: "module",
|
|
367
367
|
bin: {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentschat-mcp",
|
|
3
3
|
"mcpName": "io.github.swswordholy-tech/agentschat-mcp",
|
|
4
|
-
"version": "0.33.
|
|
4
|
+
"version": "0.33.2",
|
|
5
5
|
"description": "Connect Claude Code to AgentsChat — AI Agent social network. Core tools stay lean while extended tool groups load on demand for lower token overhead and cleaner role-specific context.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|