@hasna/conversations 0.1.31 → 0.1.32
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 +78 -3
- package/bin/mcp.js +83 -2
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -3622,7 +3622,7 @@ var init_poll = __esm(() => {
|
|
|
3622
3622
|
var require_package = __commonJS((exports, module) => {
|
|
3623
3623
|
module.exports = {
|
|
3624
3624
|
name: "@hasna/conversations",
|
|
3625
|
-
version: "0.1.
|
|
3625
|
+
version: "0.1.32",
|
|
3626
3626
|
description: "Real-time CLI messaging for AI agents",
|
|
3627
3627
|
type: "module",
|
|
3628
3628
|
bin: {
|
|
@@ -32572,11 +32572,23 @@ __export(exports_mcp, {
|
|
|
32572
32572
|
startMcpServer: () => startMcpServer,
|
|
32573
32573
|
server: () => server
|
|
32574
32574
|
});
|
|
32575
|
+
function getAgentFocus(agentId) {
|
|
32576
|
+
if (agentFocus.has(agentId))
|
|
32577
|
+
return agentFocus.get(agentId).project_id;
|
|
32578
|
+
const presence = getPresence(agentId);
|
|
32579
|
+
return presence?.project_id ?? null;
|
|
32580
|
+
}
|
|
32581
|
+
function resolveProjectId(explicitProjectId, agentId) {
|
|
32582
|
+
if (explicitProjectId)
|
|
32583
|
+
return explicitProjectId;
|
|
32584
|
+
const focused = getAgentFocus(agentId);
|
|
32585
|
+
return focused ?? undefined;
|
|
32586
|
+
}
|
|
32575
32587
|
async function startMcpServer() {
|
|
32576
32588
|
const transport = new StdioServerTransport;
|
|
32577
32589
|
await server.connect(transport);
|
|
32578
32590
|
}
|
|
32579
|
-
var import__package, server, isDirectRun;
|
|
32591
|
+
var import__package, server, agentFocus, isDirectRun;
|
|
32580
32592
|
var init_mcp2 = __esm(() => {
|
|
32581
32593
|
init_mcp();
|
|
32582
32594
|
init_stdio2();
|
|
@@ -32592,6 +32604,7 @@ var init_mcp2 = __esm(() => {
|
|
|
32592
32604
|
name: "conversations",
|
|
32593
32605
|
version: import__package.default.version
|
|
32594
32606
|
});
|
|
32607
|
+
agentFocus = new Map;
|
|
32595
32608
|
server.registerTool("send_message", {
|
|
32596
32609
|
description: "Send a DM to an agent.",
|
|
32597
32610
|
inputSchema: {
|
|
@@ -32630,7 +32643,11 @@ var init_mcp2 = __esm(() => {
|
|
|
32630
32643
|
unread_only: exports_external.coerce.boolean().optional()
|
|
32631
32644
|
}
|
|
32632
32645
|
}, async (args) => {
|
|
32633
|
-
const
|
|
32646
|
+
const agent = resolveIdentity(args.from);
|
|
32647
|
+
const messages = readMessages({
|
|
32648
|
+
...args,
|
|
32649
|
+
project_id: args.project_id ?? resolveProjectId(undefined, agent)
|
|
32650
|
+
});
|
|
32634
32651
|
return {
|
|
32635
32652
|
content: [{ type: "text", text: JSON.stringify(messages) }]
|
|
32636
32653
|
};
|
|
@@ -33222,6 +33239,58 @@ var init_mcp2 = __esm(() => {
|
|
|
33222
33239
|
content: [{ type: "text", text: JSON.stringify(messages) }]
|
|
33223
33240
|
};
|
|
33224
33241
|
});
|
|
33242
|
+
server.registerTool("set_focus", {
|
|
33243
|
+
description: "Set agent focus to a project. All read-heavy tools will default to this project scope. Stores in MCP session memory AND updates agent_presence.project_id in DB.",
|
|
33244
|
+
inputSchema: {
|
|
33245
|
+
project_id: exports_external.string(),
|
|
33246
|
+
from: exports_external.string().optional()
|
|
33247
|
+
}
|
|
33248
|
+
}, async (args) => {
|
|
33249
|
+
const { project_id, from: fromParam } = args;
|
|
33250
|
+
const agent = resolveIdentity(fromParam);
|
|
33251
|
+
agentFocus.set(agent, { project_id });
|
|
33252
|
+
const db2 = (await Promise.resolve().then(() => (init_db(), exports_db))).getDb();
|
|
33253
|
+
db2.prepare("UPDATE agent_presence SET project_id = ? WHERE agent = ?").run(project_id, agent);
|
|
33254
|
+
return {
|
|
33255
|
+
content: [{ type: "text", text: JSON.stringify({ agent, focused: true, project_id }) }]
|
|
33256
|
+
};
|
|
33257
|
+
});
|
|
33258
|
+
server.registerTool("get_focus", {
|
|
33259
|
+
description: "Get the current focus state for an agent. Returns session focus, DB project_id, and effective project_id used for filtering.",
|
|
33260
|
+
inputSchema: {
|
|
33261
|
+
from: exports_external.string().optional()
|
|
33262
|
+
}
|
|
33263
|
+
}, async (args) => {
|
|
33264
|
+
const agent = resolveIdentity(args.from);
|
|
33265
|
+
const sessionFocus = agentFocus.get(agent) ?? null;
|
|
33266
|
+
const presence = getPresence(agent);
|
|
33267
|
+
const effective = getAgentFocus(agent);
|
|
33268
|
+
return {
|
|
33269
|
+
content: [{
|
|
33270
|
+
type: "text",
|
|
33271
|
+
text: JSON.stringify({
|
|
33272
|
+
agent,
|
|
33273
|
+
session_focus: sessionFocus?.project_id ?? null,
|
|
33274
|
+
db_project_id: presence?.project_id ?? null,
|
|
33275
|
+
effective_project_id: effective
|
|
33276
|
+
})
|
|
33277
|
+
}]
|
|
33278
|
+
};
|
|
33279
|
+
});
|
|
33280
|
+
server.registerTool("unfocus", {
|
|
33281
|
+
description: "Clear agent focus. Removes session focus and clears agent_presence.project_id in DB.",
|
|
33282
|
+
inputSchema: {
|
|
33283
|
+
from: exports_external.string().optional()
|
|
33284
|
+
}
|
|
33285
|
+
}, async (args) => {
|
|
33286
|
+
const agent = resolveIdentity(args.from);
|
|
33287
|
+
agentFocus.delete(agent);
|
|
33288
|
+
const db2 = (await Promise.resolve().then(() => (init_db(), exports_db))).getDb();
|
|
33289
|
+
db2.prepare("UPDATE agent_presence SET project_id = NULL WHERE agent = ?").run(agent);
|
|
33290
|
+
return {
|
|
33291
|
+
content: [{ type: "text", text: JSON.stringify({ agent, focused: false, project_id: null }) }]
|
|
33292
|
+
};
|
|
33293
|
+
});
|
|
33225
33294
|
server.registerTool("register_agent", {
|
|
33226
33295
|
description: "Register an agent with conflict detection. Returns AgentConflictError if another active session exists (active = heartbeat within last 30 min). Optional project_id locks agent to a project for the session.",
|
|
33227
33296
|
inputSchema: {
|
|
@@ -33368,6 +33437,9 @@ var init_mcp2 = __esm(() => {
|
|
|
33368
33437
|
"pin_message",
|
|
33369
33438
|
"unpin_message",
|
|
33370
33439
|
"get_pinned_messages",
|
|
33440
|
+
"set_focus",
|
|
33441
|
+
"get_focus",
|
|
33442
|
+
"unfocus",
|
|
33371
33443
|
"register_agent",
|
|
33372
33444
|
"heartbeat",
|
|
33373
33445
|
"list_agents",
|
|
@@ -33414,6 +33486,9 @@ var init_mcp2 = __esm(() => {
|
|
|
33414
33486
|
pin_message: "Pin a message. Required: id",
|
|
33415
33487
|
unpin_message: "Unpin a message. Required: id",
|
|
33416
33488
|
get_pinned_messages: "Get pinned messages. Optional: space?, session_id?, limit?",
|
|
33489
|
+
set_focus: "Set agent focus to a project. All read tools default to this scope. Required: project_id. Optional: from?",
|
|
33490
|
+
get_focus: "Get current focus: session focus, DB project_id, effective project_id. Optional: from?",
|
|
33491
|
+
unfocus: "Clear agent focus (session + DB). Optional: from?",
|
|
33417
33492
|
register_agent: "Register agent with conflict detection (30min active window). Required: name, session_id. Optional: role?. Returns AgentConflictError if another session is active.",
|
|
33418
33493
|
heartbeat: "Register/refresh agent presence. Optional: from?, status?(online|busy|idle, default: online)",
|
|
33419
33494
|
list_agents: "List agents with presence timestamps. Optional: online_only?(only agents seen in last 60s)",
|
package/bin/mcp.js
CHANGED
|
@@ -29863,6 +29863,12 @@ function heartbeat(agent, status, metadata, sessionId) {
|
|
|
29863
29863
|
metadata = excluded.metadata
|
|
29864
29864
|
`).run(id, normalizedAgent, sessionId ?? null, resolvedStatus, metadataJson);
|
|
29865
29865
|
}
|
|
29866
|
+
function getPresence(agent) {
|
|
29867
|
+
const db2 = getDb();
|
|
29868
|
+
const normalizedAgent = agent.trim().toLowerCase();
|
|
29869
|
+
const row = db2.prepare("SELECT * FROM agent_presence WHERE LOWER(agent) = ?").get(normalizedAgent);
|
|
29870
|
+
return row ? parsePresence(row) : null;
|
|
29871
|
+
}
|
|
29866
29872
|
function listAgents(opts) {
|
|
29867
29873
|
const db2 = getDb();
|
|
29868
29874
|
let query = "SELECT * FROM agent_presence";
|
|
@@ -29895,7 +29901,7 @@ function renameAgent(oldName, newName) {
|
|
|
29895
29901
|
// package.json
|
|
29896
29902
|
var package_default = {
|
|
29897
29903
|
name: "@hasna/conversations",
|
|
29898
|
-
version: "0.1.
|
|
29904
|
+
version: "0.1.32",
|
|
29899
29905
|
description: "Real-time CLI messaging for AI agents",
|
|
29900
29906
|
type: "module",
|
|
29901
29907
|
bin: {
|
|
@@ -29977,6 +29983,19 @@ var server = new McpServer({
|
|
|
29977
29983
|
name: "conversations",
|
|
29978
29984
|
version: package_default.version
|
|
29979
29985
|
});
|
|
29986
|
+
var agentFocus = new Map;
|
|
29987
|
+
function getAgentFocus(agentId) {
|
|
29988
|
+
if (agentFocus.has(agentId))
|
|
29989
|
+
return agentFocus.get(agentId).project_id;
|
|
29990
|
+
const presence = getPresence(agentId);
|
|
29991
|
+
return presence?.project_id ?? null;
|
|
29992
|
+
}
|
|
29993
|
+
function resolveProjectId(explicitProjectId, agentId) {
|
|
29994
|
+
if (explicitProjectId)
|
|
29995
|
+
return explicitProjectId;
|
|
29996
|
+
const focused = getAgentFocus(agentId);
|
|
29997
|
+
return focused ?? undefined;
|
|
29998
|
+
}
|
|
29980
29999
|
server.registerTool("send_message", {
|
|
29981
30000
|
description: "Send a DM to an agent.",
|
|
29982
30001
|
inputSchema: {
|
|
@@ -30015,7 +30034,11 @@ server.registerTool("read_messages", {
|
|
|
30015
30034
|
unread_only: exports_external.coerce.boolean().optional()
|
|
30016
30035
|
}
|
|
30017
30036
|
}, async (args) => {
|
|
30018
|
-
const
|
|
30037
|
+
const agent = resolveIdentity(args.from);
|
|
30038
|
+
const messages = readMessages({
|
|
30039
|
+
...args,
|
|
30040
|
+
project_id: args.project_id ?? resolveProjectId(undefined, agent)
|
|
30041
|
+
});
|
|
30019
30042
|
return {
|
|
30020
30043
|
content: [{ type: "text", text: JSON.stringify(messages) }]
|
|
30021
30044
|
};
|
|
@@ -30607,6 +30630,58 @@ server.registerTool("get_pinned_messages", {
|
|
|
30607
30630
|
content: [{ type: "text", text: JSON.stringify(messages) }]
|
|
30608
30631
|
};
|
|
30609
30632
|
});
|
|
30633
|
+
server.registerTool("set_focus", {
|
|
30634
|
+
description: "Set agent focus to a project. All read-heavy tools will default to this project scope. Stores in MCP session memory AND updates agent_presence.project_id in DB.",
|
|
30635
|
+
inputSchema: {
|
|
30636
|
+
project_id: exports_external.string(),
|
|
30637
|
+
from: exports_external.string().optional()
|
|
30638
|
+
}
|
|
30639
|
+
}, async (args) => {
|
|
30640
|
+
const { project_id, from: fromParam } = args;
|
|
30641
|
+
const agent = resolveIdentity(fromParam);
|
|
30642
|
+
agentFocus.set(agent, { project_id });
|
|
30643
|
+
const db2 = (await Promise.resolve().then(() => (init_db(), exports_db))).getDb();
|
|
30644
|
+
db2.prepare("UPDATE agent_presence SET project_id = ? WHERE agent = ?").run(project_id, agent);
|
|
30645
|
+
return {
|
|
30646
|
+
content: [{ type: "text", text: JSON.stringify({ agent, focused: true, project_id }) }]
|
|
30647
|
+
};
|
|
30648
|
+
});
|
|
30649
|
+
server.registerTool("get_focus", {
|
|
30650
|
+
description: "Get the current focus state for an agent. Returns session focus, DB project_id, and effective project_id used for filtering.",
|
|
30651
|
+
inputSchema: {
|
|
30652
|
+
from: exports_external.string().optional()
|
|
30653
|
+
}
|
|
30654
|
+
}, async (args) => {
|
|
30655
|
+
const agent = resolveIdentity(args.from);
|
|
30656
|
+
const sessionFocus = agentFocus.get(agent) ?? null;
|
|
30657
|
+
const presence = getPresence(agent);
|
|
30658
|
+
const effective = getAgentFocus(agent);
|
|
30659
|
+
return {
|
|
30660
|
+
content: [{
|
|
30661
|
+
type: "text",
|
|
30662
|
+
text: JSON.stringify({
|
|
30663
|
+
agent,
|
|
30664
|
+
session_focus: sessionFocus?.project_id ?? null,
|
|
30665
|
+
db_project_id: presence?.project_id ?? null,
|
|
30666
|
+
effective_project_id: effective
|
|
30667
|
+
})
|
|
30668
|
+
}]
|
|
30669
|
+
};
|
|
30670
|
+
});
|
|
30671
|
+
server.registerTool("unfocus", {
|
|
30672
|
+
description: "Clear agent focus. Removes session focus and clears agent_presence.project_id in DB.",
|
|
30673
|
+
inputSchema: {
|
|
30674
|
+
from: exports_external.string().optional()
|
|
30675
|
+
}
|
|
30676
|
+
}, async (args) => {
|
|
30677
|
+
const agent = resolveIdentity(args.from);
|
|
30678
|
+
agentFocus.delete(agent);
|
|
30679
|
+
const db2 = (await Promise.resolve().then(() => (init_db(), exports_db))).getDb();
|
|
30680
|
+
db2.prepare("UPDATE agent_presence SET project_id = NULL WHERE agent = ?").run(agent);
|
|
30681
|
+
return {
|
|
30682
|
+
content: [{ type: "text", text: JSON.stringify({ agent, focused: false, project_id: null }) }]
|
|
30683
|
+
};
|
|
30684
|
+
});
|
|
30610
30685
|
server.registerTool("register_agent", {
|
|
30611
30686
|
description: "Register an agent with conflict detection. Returns AgentConflictError if another active session exists (active = heartbeat within last 30 min). Optional project_id locks agent to a project for the session.",
|
|
30612
30687
|
inputSchema: {
|
|
@@ -30753,6 +30828,9 @@ server.registerTool("search_tools", {
|
|
|
30753
30828
|
"pin_message",
|
|
30754
30829
|
"unpin_message",
|
|
30755
30830
|
"get_pinned_messages",
|
|
30831
|
+
"set_focus",
|
|
30832
|
+
"get_focus",
|
|
30833
|
+
"unfocus",
|
|
30756
30834
|
"register_agent",
|
|
30757
30835
|
"heartbeat",
|
|
30758
30836
|
"list_agents",
|
|
@@ -30799,6 +30877,9 @@ server.registerTool("describe_tools", {
|
|
|
30799
30877
|
pin_message: "Pin a message. Required: id",
|
|
30800
30878
|
unpin_message: "Unpin a message. Required: id",
|
|
30801
30879
|
get_pinned_messages: "Get pinned messages. Optional: space?, session_id?, limit?",
|
|
30880
|
+
set_focus: "Set agent focus to a project. All read tools default to this scope. Required: project_id. Optional: from?",
|
|
30881
|
+
get_focus: "Get current focus: session focus, DB project_id, effective project_id. Optional: from?",
|
|
30882
|
+
unfocus: "Clear agent focus (session + DB). Optional: from?",
|
|
30802
30883
|
register_agent: "Register agent with conflict detection (30min active window). Required: name, session_id. Optional: role?. Returns AgentConflictError if another session is active.",
|
|
30803
30884
|
heartbeat: "Register/refresh agent presence. Optional: from?, status?(online|busy|idle, default: online)",
|
|
30804
30885
|
list_agents: "List agents with presence timestamps. Optional: online_only?(only agents seen in last 60s)",
|