@hasna/conversations 0.2.36 → 0.2.38
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/bin/index.js +106 -90
- package/bin/mcp.js +103 -87
- package/dist/mcp/channel.d.ts +14 -7
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -14914,7 +14914,7 @@ var init_presence = __esm(() => {
|
|
|
14914
14914
|
var require_package = __commonJS((exports, module) => {
|
|
14915
14915
|
module.exports = {
|
|
14916
14916
|
name: "@hasna/conversations",
|
|
14917
|
-
version: "0.2.
|
|
14917
|
+
version: "0.2.38",
|
|
14918
14918
|
description: "Real-time CLI messaging for AI agents",
|
|
14919
14919
|
type: "module",
|
|
14920
14920
|
bin: {
|
|
@@ -44722,7 +44722,8 @@ function registerMessagingTools(server, resolveProjectId) {
|
|
|
44722
44722
|
target_session_id: exports_external2.string().optional().describe("If provided, sends to a specific agent-claude session ID (UUID). The message auto-injects into that session's conversation.")
|
|
44723
44723
|
}
|
|
44724
44724
|
}, async (args) => {
|
|
44725
|
-
const { from: fromParam, to, content, priority, blocking, project_id, target_session_id } = args;
|
|
44725
|
+
const { from: fromParam, to: toParam, to_agent, content, priority, blocking, project_id, target_session_id } = args;
|
|
44726
|
+
const to = toParam || to_agent;
|
|
44726
44727
|
const from = resolveIdentity(fromParam);
|
|
44727
44728
|
const msg = sendMessage({
|
|
44728
44729
|
from,
|
|
@@ -44804,14 +44805,16 @@ function registerMessagingTools(server, resolveProjectId) {
|
|
|
44804
44805
|
};
|
|
44805
44806
|
});
|
|
44806
44807
|
server.registerTool("reply", {
|
|
44807
|
-
description: "Reply to a specific message, creating a thread.
|
|
44808
|
+
description: "Reply to a specific message by its numeric ID, creating a thread. Use read_messages first to find the message ID.",
|
|
44808
44809
|
inputSchema: {
|
|
44809
|
-
message_id: exports_external2.coerce.number(),
|
|
44810
|
+
message_id: exports_external2.coerce.number().describe("Numeric message ID (integer) to reply to. Use read_messages to find IDs."),
|
|
44810
44811
|
content: exports_external2.string(),
|
|
44811
|
-
from: exports_external2.string().optional()
|
|
44812
|
+
from: exports_external2.string().optional(),
|
|
44813
|
+
reply_to: exports_external2.coerce.number().optional().describe("Alias for message_id")
|
|
44812
44814
|
}
|
|
44813
44815
|
}, async (args) => {
|
|
44814
|
-
const { from: fromParam, message_id, content } = args;
|
|
44816
|
+
const { from: fromParam, message_id: mid, reply_to, content } = args;
|
|
44817
|
+
const message_id = mid || reply_to;
|
|
44815
44818
|
const original = getMessageById(message_id);
|
|
44816
44819
|
if (!original) {
|
|
44817
44820
|
return {
|
|
@@ -45591,6 +45594,99 @@ var init_projects2 = __esm(() => {
|
|
|
45591
45594
|
init_identity();
|
|
45592
45595
|
});
|
|
45593
45596
|
|
|
45597
|
+
// src/mcp/channel.ts
|
|
45598
|
+
function setSessionAgent(agentId) {
|
|
45599
|
+
sessionAgentId = agentId;
|
|
45600
|
+
}
|
|
45601
|
+
function getSessionAgent() {
|
|
45602
|
+
return sessionAgentId || process.env.CONVERSATIONS_AGENT_ID || null;
|
|
45603
|
+
}
|
|
45604
|
+
function registerChannelBridge(server) {
|
|
45605
|
+
server.server.registerCapabilities({
|
|
45606
|
+
experimental: { "claude/channel": {} }
|
|
45607
|
+
});
|
|
45608
|
+
let lastAgentMsgId = 0;
|
|
45609
|
+
let lastSessionMsgId = 0;
|
|
45610
|
+
let pollTimer = null;
|
|
45611
|
+
function getSessionId() {
|
|
45612
|
+
return process.env.CONVERSATIONS_SESSION_ID || null;
|
|
45613
|
+
}
|
|
45614
|
+
function seedLastSeen() {
|
|
45615
|
+
const agent = getSessionAgent();
|
|
45616
|
+
const sid = getSessionId();
|
|
45617
|
+
if (agent) {
|
|
45618
|
+
const latest = readMessages({ to: agent, order: "desc", limit: 1 });
|
|
45619
|
+
if (latest.length > 0)
|
|
45620
|
+
lastAgentMsgId = latest[0].id;
|
|
45621
|
+
}
|
|
45622
|
+
if (sid) {
|
|
45623
|
+
const latest = readMessages({ to: `session:${sid}`, order: "desc", limit: 1 });
|
|
45624
|
+
if (latest.length > 0)
|
|
45625
|
+
lastSessionMsgId = latest[0].id;
|
|
45626
|
+
}
|
|
45627
|
+
}
|
|
45628
|
+
function pushNotification(msg, isDirect) {
|
|
45629
|
+
if (isDirect) {
|
|
45630
|
+
try {
|
|
45631
|
+
markReadByIds([msg.id]);
|
|
45632
|
+
} catch {}
|
|
45633
|
+
}
|
|
45634
|
+
const context = [
|
|
45635
|
+
`From: ${msg.from_agent}`,
|
|
45636
|
+
`Mode: ${isDirect ? "direct (auto-injected, auto-read)" : "dm (passive, check inbox)"}`,
|
|
45637
|
+
`Message ID: ${msg.id}`,
|
|
45638
|
+
msg.space ? `Space: ${msg.space}` : null,
|
|
45639
|
+
msg.priority && msg.priority !== "normal" ? `Priority: ${msg.priority}` : null
|
|
45640
|
+
].filter(Boolean).join(" | ");
|
|
45641
|
+
const enrichedContent = `[${context}]
|
|
45642
|
+
${msg.content}`;
|
|
45643
|
+
server.server.notification({
|
|
45644
|
+
method: "notifications/claude/channel",
|
|
45645
|
+
params: {
|
|
45646
|
+
content: enrichedContent,
|
|
45647
|
+
meta: {
|
|
45648
|
+
from: msg.from_agent,
|
|
45649
|
+
message_id: String(msg.id),
|
|
45650
|
+
session_id: msg.session_id,
|
|
45651
|
+
mode: isDirect ? "direct" : "dm",
|
|
45652
|
+
...msg.space ? { space: msg.space } : {},
|
|
45653
|
+
...msg.priority && msg.priority !== "normal" ? { priority: msg.priority } : {}
|
|
45654
|
+
}
|
|
45655
|
+
}
|
|
45656
|
+
}).catch(() => {});
|
|
45657
|
+
}
|
|
45658
|
+
function startPolling2() {
|
|
45659
|
+
if (pollTimer)
|
|
45660
|
+
return;
|
|
45661
|
+
seedLastSeen();
|
|
45662
|
+
pollTimer = setInterval(() => {
|
|
45663
|
+
try {
|
|
45664
|
+
const agent = getSessionAgent();
|
|
45665
|
+
const sid = getSessionId();
|
|
45666
|
+
if (agent) {
|
|
45667
|
+
const msgs = readMessages({ to: agent, order: "asc", limit: 20 }).filter((m) => m.id > lastAgentMsgId);
|
|
45668
|
+
for (const msg of msgs) {
|
|
45669
|
+
lastAgentMsgId = msg.id;
|
|
45670
|
+
pushNotification(msg, false);
|
|
45671
|
+
}
|
|
45672
|
+
}
|
|
45673
|
+
if (sid) {
|
|
45674
|
+
const msgs = readMessages({ to: `session:${sid}`, order: "asc", limit: 20 }).filter((m) => m.id > lastSessionMsgId);
|
|
45675
|
+
for (const msg of msgs) {
|
|
45676
|
+
lastSessionMsgId = msg.id;
|
|
45677
|
+
pushNotification(msg, true);
|
|
45678
|
+
}
|
|
45679
|
+
}
|
|
45680
|
+
} catch {}
|
|
45681
|
+
}, POLL_INTERVAL_MS);
|
|
45682
|
+
}
|
|
45683
|
+
setTimeout(() => startPolling2(), 2000);
|
|
45684
|
+
}
|
|
45685
|
+
var POLL_INTERVAL_MS = 1000, sessionAgentId = null;
|
|
45686
|
+
var init_channel = __esm(() => {
|
|
45687
|
+
init_messages();
|
|
45688
|
+
});
|
|
45689
|
+
|
|
45594
45690
|
// src/mcp/tools/agents.ts
|
|
45595
45691
|
function registerAgentTools(server, agentFocus, getAgentFocus) {
|
|
45596
45692
|
server.registerTool("register_agent", {
|
|
@@ -45605,6 +45701,7 @@ function registerAgentTools(server, agentFocus, getAgentFocus) {
|
|
|
45605
45701
|
const { name, session_id, role, project_id } = args;
|
|
45606
45702
|
try {
|
|
45607
45703
|
const result = registerAgent(name, session_id, role, project_id);
|
|
45704
|
+
setSessionAgent(name);
|
|
45608
45705
|
return {
|
|
45609
45706
|
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
45610
45707
|
};
|
|
@@ -45628,6 +45725,7 @@ function registerAgentTools(server, agentFocus, getAgentFocus) {
|
|
|
45628
45725
|
const { from: fromParam, status } = args;
|
|
45629
45726
|
const agent = resolveIdentity(fromParam);
|
|
45630
45727
|
heartbeat(agent, status);
|
|
45728
|
+
setSessionAgent(agent);
|
|
45631
45729
|
return {
|
|
45632
45730
|
content: [{ type: "text", text: JSON.stringify({ agent, status: status || "online", heartbeat: true }) }]
|
|
45633
45731
|
};
|
|
@@ -45784,6 +45882,7 @@ var init_agents = __esm(() => {
|
|
|
45784
45882
|
init_zod2();
|
|
45785
45883
|
init_identity();
|
|
45786
45884
|
init_presence();
|
|
45885
|
+
init_channel();
|
|
45787
45886
|
init_sessions();
|
|
45788
45887
|
init_messages();
|
|
45789
45888
|
});
|
|
@@ -46927,89 +47026,6 @@ var init_cloud = __esm(() => {
|
|
|
46927
47026
|
CONFLICT_TABLES = new Set(["spaces", "projects", "agent_presence"]);
|
|
46928
47027
|
});
|
|
46929
47028
|
|
|
46930
|
-
// src/mcp/channel.ts
|
|
46931
|
-
function registerChannelBridge(server, getAgentId, getSessionId) {
|
|
46932
|
-
server.server.registerCapabilities({
|
|
46933
|
-
experimental: {
|
|
46934
|
-
"claude/channel": {}
|
|
46935
|
-
}
|
|
46936
|
-
});
|
|
46937
|
-
let lastSeenId = 0;
|
|
46938
|
-
let lastSeenSessionId = 0;
|
|
46939
|
-
let pollTimer = null;
|
|
46940
|
-
function seedLastSeen(agentId, sessionId) {
|
|
46941
|
-
const latestAgent = readMessages({ to: agentId, order: "desc", limit: 1 });
|
|
46942
|
-
if (latestAgent.length > 0)
|
|
46943
|
-
lastSeenId = latestAgent[0].id;
|
|
46944
|
-
if (sessionId) {
|
|
46945
|
-
const latestSession = readMessages({ to: `session:${sessionId}`, order: "desc", limit: 1 });
|
|
46946
|
-
if (latestSession.length > 0)
|
|
46947
|
-
lastSeenSessionId = latestSession[0].id;
|
|
46948
|
-
}
|
|
46949
|
-
}
|
|
46950
|
-
function pushNotification(msg) {
|
|
46951
|
-
console.error(`[channel-bridge] pushing notification: from=${msg.from_agent}, content=${msg.content.slice(0, 50)}`);
|
|
46952
|
-
server.server.notification({
|
|
46953
|
-
method: "notifications/claude/channel",
|
|
46954
|
-
params: {
|
|
46955
|
-
content: msg.content,
|
|
46956
|
-
meta: {
|
|
46957
|
-
from: msg.from_agent,
|
|
46958
|
-
session_id: msg.session_id,
|
|
46959
|
-
...msg.space ? { space: msg.space } : {},
|
|
46960
|
-
...msg.priority && msg.priority !== "normal" ? { priority: msg.priority } : {}
|
|
46961
|
-
}
|
|
46962
|
-
}
|
|
46963
|
-
});
|
|
46964
|
-
}
|
|
46965
|
-
function startPolling2() {
|
|
46966
|
-
if (pollTimer)
|
|
46967
|
-
return;
|
|
46968
|
-
const agentId = getAgentId();
|
|
46969
|
-
const sessionId = getSessionId();
|
|
46970
|
-
console.error(`[channel-bridge] startPolling: agentId=${agentId}, sessionId=${sessionId}`);
|
|
46971
|
-
if (!agentId && !sessionId) {
|
|
46972
|
-
console.error("[channel-bridge] no agentId or sessionId \u2014 not polling");
|
|
46973
|
-
return;
|
|
46974
|
-
}
|
|
46975
|
-
if (agentId)
|
|
46976
|
-
seedLastSeen(agentId, sessionId);
|
|
46977
|
-
pollTimer = setInterval(() => {
|
|
46978
|
-
try {
|
|
46979
|
-
const currentAgent = getAgentId();
|
|
46980
|
-
const currentSession = getSessionId();
|
|
46981
|
-
if (currentAgent) {
|
|
46982
|
-
const newAgentMsgs = readMessages({
|
|
46983
|
-
to: currentAgent,
|
|
46984
|
-
order: "asc",
|
|
46985
|
-
limit: 20
|
|
46986
|
-
}).filter((m) => m.id > lastSeenId);
|
|
46987
|
-
for (const msg of newAgentMsgs) {
|
|
46988
|
-
lastSeenId = msg.id;
|
|
46989
|
-
pushNotification(msg);
|
|
46990
|
-
}
|
|
46991
|
-
}
|
|
46992
|
-
if (currentSession) {
|
|
46993
|
-
const newSessionMsgs = readMessages({
|
|
46994
|
-
to: `session:${currentSession}`,
|
|
46995
|
-
order: "asc",
|
|
46996
|
-
limit: 20
|
|
46997
|
-
}).filter((m) => m.id > lastSeenSessionId);
|
|
46998
|
-
for (const msg of newSessionMsgs) {
|
|
46999
|
-
lastSeenSessionId = msg.id;
|
|
47000
|
-
pushNotification(msg);
|
|
47001
|
-
}
|
|
47002
|
-
}
|
|
47003
|
-
} catch {}
|
|
47004
|
-
}, POLL_INTERVAL_MS);
|
|
47005
|
-
}
|
|
47006
|
-
setTimeout(() => startPolling2(), 500);
|
|
47007
|
-
}
|
|
47008
|
-
var POLL_INTERVAL_MS = 1000;
|
|
47009
|
-
var init_channel = __esm(() => {
|
|
47010
|
-
init_messages();
|
|
47011
|
-
});
|
|
47012
|
-
|
|
47013
47029
|
// src/mcp/tools/tmux.ts
|
|
47014
47030
|
function sleep2(ms) {
|
|
47015
47031
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -47163,7 +47179,7 @@ var init_mcp2 = __esm(() => {
|
|
|
47163
47179
|
registerAgentTools(server, agentFocus, getAgentFocus);
|
|
47164
47180
|
registerAdvancedTools(server, import__package2.default.version);
|
|
47165
47181
|
registerTmuxTools(server);
|
|
47166
|
-
registerChannelBridge(server
|
|
47182
|
+
registerChannelBridge(server);
|
|
47167
47183
|
isDirectRun = import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith("mcp.js") || process.argv[1]?.endsWith("mcp.ts");
|
|
47168
47184
|
if (isDirectRun) {
|
|
47169
47185
|
startMcpServer().catch((error48) => {
|
package/bin/mcp.js
CHANGED
|
@@ -41218,7 +41218,8 @@ function registerMessagingTools(server, resolveProjectId) {
|
|
|
41218
41218
|
target_session_id: exports_external.string().optional().describe("If provided, sends to a specific agent-claude session ID (UUID). The message auto-injects into that session's conversation.")
|
|
41219
41219
|
}
|
|
41220
41220
|
}, async (args) => {
|
|
41221
|
-
const { from: fromParam, to, content, priority, blocking, project_id, target_session_id } = args;
|
|
41221
|
+
const { from: fromParam, to: toParam, to_agent, content, priority, blocking, project_id, target_session_id } = args;
|
|
41222
|
+
const to = toParam || to_agent;
|
|
41222
41223
|
const from = resolveIdentity(fromParam);
|
|
41223
41224
|
const msg = sendMessage({
|
|
41224
41225
|
from,
|
|
@@ -41300,14 +41301,16 @@ function registerMessagingTools(server, resolveProjectId) {
|
|
|
41300
41301
|
};
|
|
41301
41302
|
});
|
|
41302
41303
|
server.registerTool("reply", {
|
|
41303
|
-
description: "Reply to a specific message, creating a thread.
|
|
41304
|
+
description: "Reply to a specific message by its numeric ID, creating a thread. Use read_messages first to find the message ID.",
|
|
41304
41305
|
inputSchema: {
|
|
41305
|
-
message_id: exports_external.coerce.number(),
|
|
41306
|
+
message_id: exports_external.coerce.number().describe("Numeric message ID (integer) to reply to. Use read_messages to find IDs."),
|
|
41306
41307
|
content: exports_external.string(),
|
|
41307
|
-
from: exports_external.string().optional()
|
|
41308
|
+
from: exports_external.string().optional(),
|
|
41309
|
+
reply_to: exports_external.coerce.number().optional().describe("Alias for message_id")
|
|
41308
41310
|
}
|
|
41309
41311
|
}, async (args) => {
|
|
41310
|
-
const { from: fromParam, message_id, content } = args;
|
|
41312
|
+
const { from: fromParam, message_id: mid, reply_to, content } = args;
|
|
41313
|
+
const message_id = mid || reply_to;
|
|
41311
41314
|
const original = getMessageById(message_id);
|
|
41312
41315
|
if (!original) {
|
|
41313
41316
|
return {
|
|
@@ -42423,6 +42426,97 @@ function registerProjectTools(server) {
|
|
|
42423
42426
|
});
|
|
42424
42427
|
}
|
|
42425
42428
|
|
|
42429
|
+
// src/mcp/channel.ts
|
|
42430
|
+
var POLL_INTERVAL_MS = 1000;
|
|
42431
|
+
var sessionAgentId = null;
|
|
42432
|
+
function setSessionAgent(agentId) {
|
|
42433
|
+
sessionAgentId = agentId;
|
|
42434
|
+
}
|
|
42435
|
+
function getSessionAgent() {
|
|
42436
|
+
return sessionAgentId || process.env.CONVERSATIONS_AGENT_ID || null;
|
|
42437
|
+
}
|
|
42438
|
+
function registerChannelBridge(server) {
|
|
42439
|
+
server.server.registerCapabilities({
|
|
42440
|
+
experimental: { "claude/channel": {} }
|
|
42441
|
+
});
|
|
42442
|
+
let lastAgentMsgId = 0;
|
|
42443
|
+
let lastSessionMsgId = 0;
|
|
42444
|
+
let pollTimer = null;
|
|
42445
|
+
function getSessionId() {
|
|
42446
|
+
return process.env.CONVERSATIONS_SESSION_ID || null;
|
|
42447
|
+
}
|
|
42448
|
+
function seedLastSeen() {
|
|
42449
|
+
const agent = getSessionAgent();
|
|
42450
|
+
const sid = getSessionId();
|
|
42451
|
+
if (agent) {
|
|
42452
|
+
const latest = readMessages({ to: agent, order: "desc", limit: 1 });
|
|
42453
|
+
if (latest.length > 0)
|
|
42454
|
+
lastAgentMsgId = latest[0].id;
|
|
42455
|
+
}
|
|
42456
|
+
if (sid) {
|
|
42457
|
+
const latest = readMessages({ to: `session:${sid}`, order: "desc", limit: 1 });
|
|
42458
|
+
if (latest.length > 0)
|
|
42459
|
+
lastSessionMsgId = latest[0].id;
|
|
42460
|
+
}
|
|
42461
|
+
}
|
|
42462
|
+
function pushNotification(msg, isDirect) {
|
|
42463
|
+
if (isDirect) {
|
|
42464
|
+
try {
|
|
42465
|
+
markReadByIds([msg.id]);
|
|
42466
|
+
} catch {}
|
|
42467
|
+
}
|
|
42468
|
+
const context = [
|
|
42469
|
+
`From: ${msg.from_agent}`,
|
|
42470
|
+
`Mode: ${isDirect ? "direct (auto-injected, auto-read)" : "dm (passive, check inbox)"}`,
|
|
42471
|
+
`Message ID: ${msg.id}`,
|
|
42472
|
+
msg.space ? `Space: ${msg.space}` : null,
|
|
42473
|
+
msg.priority && msg.priority !== "normal" ? `Priority: ${msg.priority}` : null
|
|
42474
|
+
].filter(Boolean).join(" | ");
|
|
42475
|
+
const enrichedContent = `[${context}]
|
|
42476
|
+
${msg.content}`;
|
|
42477
|
+
server.server.notification({
|
|
42478
|
+
method: "notifications/claude/channel",
|
|
42479
|
+
params: {
|
|
42480
|
+
content: enrichedContent,
|
|
42481
|
+
meta: {
|
|
42482
|
+
from: msg.from_agent,
|
|
42483
|
+
message_id: String(msg.id),
|
|
42484
|
+
session_id: msg.session_id,
|
|
42485
|
+
mode: isDirect ? "direct" : "dm",
|
|
42486
|
+
...msg.space ? { space: msg.space } : {},
|
|
42487
|
+
...msg.priority && msg.priority !== "normal" ? { priority: msg.priority } : {}
|
|
42488
|
+
}
|
|
42489
|
+
}
|
|
42490
|
+
}).catch(() => {});
|
|
42491
|
+
}
|
|
42492
|
+
function startPolling() {
|
|
42493
|
+
if (pollTimer)
|
|
42494
|
+
return;
|
|
42495
|
+
seedLastSeen();
|
|
42496
|
+
pollTimer = setInterval(() => {
|
|
42497
|
+
try {
|
|
42498
|
+
const agent = getSessionAgent();
|
|
42499
|
+
const sid = getSessionId();
|
|
42500
|
+
if (agent) {
|
|
42501
|
+
const msgs = readMessages({ to: agent, order: "asc", limit: 20 }).filter((m) => m.id > lastAgentMsgId);
|
|
42502
|
+
for (const msg of msgs) {
|
|
42503
|
+
lastAgentMsgId = msg.id;
|
|
42504
|
+
pushNotification(msg, false);
|
|
42505
|
+
}
|
|
42506
|
+
}
|
|
42507
|
+
if (sid) {
|
|
42508
|
+
const msgs = readMessages({ to: `session:${sid}`, order: "asc", limit: 20 }).filter((m) => m.id > lastSessionMsgId);
|
|
42509
|
+
for (const msg of msgs) {
|
|
42510
|
+
lastSessionMsgId = msg.id;
|
|
42511
|
+
pushNotification(msg, true);
|
|
42512
|
+
}
|
|
42513
|
+
}
|
|
42514
|
+
} catch {}
|
|
42515
|
+
}, POLL_INTERVAL_MS);
|
|
42516
|
+
}
|
|
42517
|
+
setTimeout(() => startPolling(), 2000);
|
|
42518
|
+
}
|
|
42519
|
+
|
|
42426
42520
|
// src/mcp/tools/agents.ts
|
|
42427
42521
|
function registerAgentTools(server, agentFocus, getAgentFocus) {
|
|
42428
42522
|
server.registerTool("register_agent", {
|
|
@@ -42437,6 +42531,7 @@ function registerAgentTools(server, agentFocus, getAgentFocus) {
|
|
|
42437
42531
|
const { name, session_id, role, project_id } = args;
|
|
42438
42532
|
try {
|
|
42439
42533
|
const result = registerAgent(name, session_id, role, project_id);
|
|
42534
|
+
setSessionAgent(name);
|
|
42440
42535
|
return {
|
|
42441
42536
|
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
42442
42537
|
};
|
|
@@ -42460,6 +42555,7 @@ function registerAgentTools(server, agentFocus, getAgentFocus) {
|
|
|
42460
42555
|
const { from: fromParam, status } = args;
|
|
42461
42556
|
const agent = resolveIdentity(fromParam);
|
|
42462
42557
|
heartbeat(agent, status);
|
|
42558
|
+
setSessionAgent(agent);
|
|
42463
42559
|
return {
|
|
42464
42560
|
content: [{ type: "text", text: JSON.stringify({ agent, status: status || "online", heartbeat: true }) }]
|
|
42465
42561
|
};
|
|
@@ -44073,86 +44169,6 @@ function formatError2(e) {
|
|
|
44073
44169
|
return String(e);
|
|
44074
44170
|
}
|
|
44075
44171
|
|
|
44076
|
-
// src/mcp/channel.ts
|
|
44077
|
-
var POLL_INTERVAL_MS = 1000;
|
|
44078
|
-
function registerChannelBridge(server, getAgentId, getSessionId) {
|
|
44079
|
-
server.server.registerCapabilities({
|
|
44080
|
-
experimental: {
|
|
44081
|
-
"claude/channel": {}
|
|
44082
|
-
}
|
|
44083
|
-
});
|
|
44084
|
-
let lastSeenId = 0;
|
|
44085
|
-
let lastSeenSessionId = 0;
|
|
44086
|
-
let pollTimer = null;
|
|
44087
|
-
function seedLastSeen(agentId, sessionId) {
|
|
44088
|
-
const latestAgent = readMessages({ to: agentId, order: "desc", limit: 1 });
|
|
44089
|
-
if (latestAgent.length > 0)
|
|
44090
|
-
lastSeenId = latestAgent[0].id;
|
|
44091
|
-
if (sessionId) {
|
|
44092
|
-
const latestSession = readMessages({ to: `session:${sessionId}`, order: "desc", limit: 1 });
|
|
44093
|
-
if (latestSession.length > 0)
|
|
44094
|
-
lastSeenSessionId = latestSession[0].id;
|
|
44095
|
-
}
|
|
44096
|
-
}
|
|
44097
|
-
function pushNotification(msg) {
|
|
44098
|
-
console.error(`[channel-bridge] pushing notification: from=${msg.from_agent}, content=${msg.content.slice(0, 50)}`);
|
|
44099
|
-
server.server.notification({
|
|
44100
|
-
method: "notifications/claude/channel",
|
|
44101
|
-
params: {
|
|
44102
|
-
content: msg.content,
|
|
44103
|
-
meta: {
|
|
44104
|
-
from: msg.from_agent,
|
|
44105
|
-
session_id: msg.session_id,
|
|
44106
|
-
...msg.space ? { space: msg.space } : {},
|
|
44107
|
-
...msg.priority && msg.priority !== "normal" ? { priority: msg.priority } : {}
|
|
44108
|
-
}
|
|
44109
|
-
}
|
|
44110
|
-
});
|
|
44111
|
-
}
|
|
44112
|
-
function startPolling() {
|
|
44113
|
-
if (pollTimer)
|
|
44114
|
-
return;
|
|
44115
|
-
const agentId = getAgentId();
|
|
44116
|
-
const sessionId = getSessionId();
|
|
44117
|
-
console.error(`[channel-bridge] startPolling: agentId=${agentId}, sessionId=${sessionId}`);
|
|
44118
|
-
if (!agentId && !sessionId) {
|
|
44119
|
-
console.error("[channel-bridge] no agentId or sessionId \u2014 not polling");
|
|
44120
|
-
return;
|
|
44121
|
-
}
|
|
44122
|
-
if (agentId)
|
|
44123
|
-
seedLastSeen(agentId, sessionId);
|
|
44124
|
-
pollTimer = setInterval(() => {
|
|
44125
|
-
try {
|
|
44126
|
-
const currentAgent = getAgentId();
|
|
44127
|
-
const currentSession = getSessionId();
|
|
44128
|
-
if (currentAgent) {
|
|
44129
|
-
const newAgentMsgs = readMessages({
|
|
44130
|
-
to: currentAgent,
|
|
44131
|
-
order: "asc",
|
|
44132
|
-
limit: 20
|
|
44133
|
-
}).filter((m) => m.id > lastSeenId);
|
|
44134
|
-
for (const msg of newAgentMsgs) {
|
|
44135
|
-
lastSeenId = msg.id;
|
|
44136
|
-
pushNotification(msg);
|
|
44137
|
-
}
|
|
44138
|
-
}
|
|
44139
|
-
if (currentSession) {
|
|
44140
|
-
const newSessionMsgs = readMessages({
|
|
44141
|
-
to: `session:${currentSession}`,
|
|
44142
|
-
order: "asc",
|
|
44143
|
-
limit: 20
|
|
44144
|
-
}).filter((m) => m.id > lastSeenSessionId);
|
|
44145
|
-
for (const msg of newSessionMsgs) {
|
|
44146
|
-
lastSeenSessionId = msg.id;
|
|
44147
|
-
pushNotification(msg);
|
|
44148
|
-
}
|
|
44149
|
-
}
|
|
44150
|
-
} catch {}
|
|
44151
|
-
}, POLL_INTERVAL_MS);
|
|
44152
|
-
}
|
|
44153
|
-
setTimeout(() => startPolling(), 500);
|
|
44154
|
-
}
|
|
44155
|
-
|
|
44156
44172
|
// src/cli/commands/tmux.ts
|
|
44157
44173
|
import { execSync } from "child_process";
|
|
44158
44174
|
function sleep(ms) {
|
|
@@ -44301,7 +44317,7 @@ function registerTmuxTools(server) {
|
|
|
44301
44317
|
// package.json
|
|
44302
44318
|
var package_default = {
|
|
44303
44319
|
name: "@hasna/conversations",
|
|
44304
|
-
version: "0.2.
|
|
44320
|
+
version: "0.2.38",
|
|
44305
44321
|
description: "Real-time CLI messaging for AI agents",
|
|
44306
44322
|
type: "module",
|
|
44307
44323
|
bin: {
|
|
@@ -44404,7 +44420,7 @@ registerProjectTools(server);
|
|
|
44404
44420
|
registerAgentTools(server, agentFocus, getAgentFocus);
|
|
44405
44421
|
registerAdvancedTools(server, package_default.version);
|
|
44406
44422
|
registerTmuxTools(server);
|
|
44407
|
-
registerChannelBridge(server
|
|
44423
|
+
registerChannelBridge(server);
|
|
44408
44424
|
async function startMcpServer() {
|
|
44409
44425
|
const transport = new StdioServerTransport;
|
|
44410
44426
|
registerCloudSyncTools(server);
|
package/dist/mcp/channel.d.ts
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Claude Code channel bridge for conversations MCP server.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Two messaging modes:
|
|
5
|
+
* 1. Direct inject (send_to_session) — targets session ID, auto-injected
|
|
6
|
+
* via channel notification, auto-marked as read
|
|
7
|
+
* 2. DM (send_message) — targets agent name, sits in inbox unread
|
|
8
|
+
* until the agent checks, also injected if agent is online
|
|
6
9
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
+
* The bridge figures out who it is from:
|
|
11
|
+
* - The agent that registered/heartbeated in this MCP session
|
|
12
|
+
* - The CONVERSATIONS_SESSION_ID env var (set by agent-claude)
|
|
13
|
+
* - Falls back to CONVERSATIONS_AGENT_ID if set
|
|
10
14
|
*
|
|
11
|
-
*
|
|
15
|
+
* No manual config needed — just connect and go.
|
|
12
16
|
*/
|
|
13
17
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
14
|
-
|
|
18
|
+
/** Called by agent tools when register_agent or heartbeat fires */
|
|
19
|
+
export declare function setSessionAgent(agentId: string): void;
|
|
20
|
+
export declare function getSessionAgent(): string | null;
|
|
21
|
+
export declare function registerChannelBridge(server: McpServer): void;
|