@hasna/conversations 0.2.7 → 0.2.9
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 +24 -7
- package/bin/mcp.js +30 -7
- package/dist/index.js +3 -2
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -2395,9 +2395,10 @@ function readMessages(opts = {}) {
|
|
|
2395
2395
|
conditions.push(`id IN (SELECT message_id FROM message_mentions WHERE mentioned_agent = ?)`);
|
|
2396
2396
|
params.push(opts.mentions_only.toLowerCase());
|
|
2397
2397
|
}
|
|
2398
|
+
const isLatest = opts.latest && opts.latest > 0;
|
|
2398
2399
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
2399
|
-
const resolvedLimit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
|
|
2400
|
-
const order = opts.order?.toLowerCase() === "desc" ? "DESC" : "ASC";
|
|
2400
|
+
const resolvedLimit = isLatest ? Math.floor(opts.latest) : Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
|
|
2401
|
+
const order = isLatest ? "DESC" : opts.order?.toLowerCase() === "desc" ? "DESC" : "ASC";
|
|
2401
2402
|
const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} LIMIT ${resolvedLimit}`).all(...params);
|
|
2402
2403
|
let messages = rows.map(parseMessage);
|
|
2403
2404
|
if (opts.include_reply_counts && messages.length > 0) {
|
|
@@ -4440,7 +4441,7 @@ var init_poll = __esm(() => {
|
|
|
4440
4441
|
var require_package = __commonJS((exports, module) => {
|
|
4441
4442
|
module.exports = {
|
|
4442
4443
|
name: "@hasna/conversations",
|
|
4443
|
-
version: "0.2.
|
|
4444
|
+
version: "0.2.9",
|
|
4444
4445
|
description: "Real-time CLI messaging for AI agents",
|
|
4445
4446
|
type: "module",
|
|
4446
4447
|
bin: {
|
|
@@ -33696,7 +33697,8 @@ var init_mcp2 = __esm(() => {
|
|
|
33696
33697
|
max_content_length: exports_external.coerce.number().optional().describe("Truncate each message content to N chars (adds truncated:true flag)"),
|
|
33697
33698
|
threads_only: exports_external.coerce.boolean().optional().describe("Only return root messages (reply_to IS NULL) \u2014 hides thread replies"),
|
|
33698
33699
|
include_reply_counts: exports_external.coerce.boolean().optional().describe("Include reply_count on each message (adds one extra query)"),
|
|
33699
|
-
mentions_only: exports_external.string().optional().describe("Only return messages that @mention this agent")
|
|
33700
|
+
mentions_only: exports_external.string().optional().describe("Only return messages that @mention this agent"),
|
|
33701
|
+
latest: exports_external.coerce.number().optional().describe("Return the N most recent unread messages, newest first. Shorthand for order:desc + limit:N.")
|
|
33700
33702
|
}
|
|
33701
33703
|
}, async (args) => {
|
|
33702
33704
|
const agent = resolveIdentity(args.from);
|
|
@@ -33778,6 +33780,19 @@ var init_mcp2 = __esm(() => {
|
|
|
33778
33780
|
content: [{ type: "text", text: JSON.stringify({ marked_read: count }) }]
|
|
33779
33781
|
};
|
|
33780
33782
|
});
|
|
33783
|
+
server.registerTool("mark_space_read", {
|
|
33784
|
+
description: "Mark ALL messages in a space as read without fetching them. Use this on busy spaces (200+ messages) where read_messages would overflow tokens.",
|
|
33785
|
+
inputSchema: {
|
|
33786
|
+
space: exports_external.string().describe("Space name"),
|
|
33787
|
+
from: exports_external.string().optional().describe("Mark read on behalf of this agent (default: current agent)")
|
|
33788
|
+
}
|
|
33789
|
+
}, async (args) => {
|
|
33790
|
+
const { space, from: fromParam } = args;
|
|
33791
|
+
const count = markSpaceRead(space, fromParam);
|
|
33792
|
+
return {
|
|
33793
|
+
content: [{ type: "text", text: JSON.stringify({ space, marked_read: count }) }]
|
|
33794
|
+
};
|
|
33795
|
+
});
|
|
33781
33796
|
server.registerTool("search_messages", {
|
|
33782
33797
|
description: "Full-text search across messages. Uses FTS5 with BM25 ranking if available, falls back to LIKE. Returns messages with snippet and relevance_score.",
|
|
33783
33798
|
inputSchema: {
|
|
@@ -33953,11 +33968,12 @@ var init_mcp2 = __esm(() => {
|
|
|
33953
33968
|
mark_read: exports_external.coerce.boolean().optional(),
|
|
33954
33969
|
max_content_length: exports_external.coerce.number().optional().describe("Truncate each message content to N chars (adds truncated:true flag)"),
|
|
33955
33970
|
threads_only: exports_external.coerce.boolean().optional().describe("Only return root messages (hides thread replies)"),
|
|
33956
|
-
include_reply_counts: exports_external.coerce.boolean().optional().describe("Include reply_count on each message")
|
|
33971
|
+
include_reply_counts: exports_external.coerce.boolean().optional().describe("Include reply_count on each message"),
|
|
33972
|
+
latest: exports_external.coerce.number().optional().describe("Return the N most recent messages, newest first")
|
|
33957
33973
|
}
|
|
33958
33974
|
}, async (args) => {
|
|
33959
|
-
const { space, since, limit, mark_read, max_content_length, threads_only, include_reply_counts } = args;
|
|
33960
|
-
const messages = readMessages({ space, since, limit, max_content_length, threads_only, include_reply_counts });
|
|
33975
|
+
const { space, since, limit, mark_read, max_content_length, threads_only, include_reply_counts, latest } = args;
|
|
33976
|
+
const messages = readMessages({ space, since, limit, max_content_length, threads_only, include_reply_counts, latest });
|
|
33961
33977
|
if (mark_read !== false && messages.length > 0) {
|
|
33962
33978
|
markReadByIds(messages.map((m) => m.id));
|
|
33963
33979
|
}
|
|
@@ -34881,6 +34897,7 @@ var init_mcp2 = __esm(() => {
|
|
|
34881
34897
|
list_sessions: "List all DM sessions. Optional: agent?(filter by participant)",
|
|
34882
34898
|
reply: "Reply to a specific message, creating a thread (sets reply_to). Use read_thread to retrieve. Required: message_id, content. Optional: from?",
|
|
34883
34899
|
mark_read: "Mark messages as read. Optional: from?, ids?(array), all?(bool \u2014 mark all unread)",
|
|
34900
|
+
mark_space_read: "Mark ALL messages in a space as read without fetching. Required: space. Optional: from?",
|
|
34884
34901
|
search_messages: "Full-text search messages. Required: query. Optional: space?, from?, to?, limit?",
|
|
34885
34902
|
export_messages: "Export messages as JSON or CSV. Optional: space?, session_id?, from?, since?, until?, format?(json|csv)",
|
|
34886
34903
|
create_space: "Create space and auto-join. Required: name. Optional: from?, description?, parent_id?(max 3 levels), project_id?",
|
package/bin/mcp.js
CHANGED
|
@@ -28904,9 +28904,10 @@ function readMessages(opts = {}) {
|
|
|
28904
28904
|
conditions.push(`id IN (SELECT message_id FROM message_mentions WHERE mentioned_agent = ?)`);
|
|
28905
28905
|
params.push(opts.mentions_only.toLowerCase());
|
|
28906
28906
|
}
|
|
28907
|
+
const isLatest = opts.latest && opts.latest > 0;
|
|
28907
28908
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
28908
|
-
const resolvedLimit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
|
|
28909
|
-
const order = opts.order?.toLowerCase() === "desc" ? "DESC" : "ASC";
|
|
28909
|
+
const resolvedLimit = isLatest ? Math.floor(opts.latest) : Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
|
|
28910
|
+
const order = isLatest ? "DESC" : opts.order?.toLowerCase() === "desc" ? "DESC" : "ASC";
|
|
28910
28911
|
const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} LIMIT ${resolvedLimit}`).all(...params);
|
|
28911
28912
|
let messages = rows.map(parseMessage);
|
|
28912
28913
|
if (opts.include_reply_counts && messages.length > 0) {
|
|
@@ -28936,6 +28937,12 @@ function markRead(ids, reader) {
|
|
|
28936
28937
|
const result = stmt.run(...ids, reader);
|
|
28937
28938
|
return result.changes;
|
|
28938
28939
|
}
|
|
28940
|
+
function markSpaceRead(spaceName, reader) {
|
|
28941
|
+
const db2 = getDb();
|
|
28942
|
+
const stmt = db2.prepare(`UPDATE messages SET read_at = strftime('%Y-%m-%dT%H:%M:%f', 'now') WHERE space = ? AND from_agent != ? AND read_at IS NULL`);
|
|
28943
|
+
const result = stmt.run(spaceName, reader);
|
|
28944
|
+
return result.changes;
|
|
28945
|
+
}
|
|
28939
28946
|
function getMessageById(id) {
|
|
28940
28947
|
const db2 = getDb();
|
|
28941
28948
|
const row = db2.prepare("SELECT * FROM messages WHERE id = ?").get(id);
|
|
@@ -30924,7 +30931,7 @@ function getGraphStats() {
|
|
|
30924
30931
|
// package.json
|
|
30925
30932
|
var package_default = {
|
|
30926
30933
|
name: "@hasna/conversations",
|
|
30927
|
-
version: "0.2.
|
|
30934
|
+
version: "0.2.9",
|
|
30928
30935
|
description: "Real-time CLI messaging for AI agents",
|
|
30929
30936
|
type: "module",
|
|
30930
30937
|
bin: {
|
|
@@ -31059,7 +31066,8 @@ server.registerTool("read_messages", {
|
|
|
31059
31066
|
max_content_length: exports_external.coerce.number().optional().describe("Truncate each message content to N chars (adds truncated:true flag)"),
|
|
31060
31067
|
threads_only: exports_external.coerce.boolean().optional().describe("Only return root messages (reply_to IS NULL) \u2014 hides thread replies"),
|
|
31061
31068
|
include_reply_counts: exports_external.coerce.boolean().optional().describe("Include reply_count on each message (adds one extra query)"),
|
|
31062
|
-
mentions_only: exports_external.string().optional().describe("Only return messages that @mention this agent")
|
|
31069
|
+
mentions_only: exports_external.string().optional().describe("Only return messages that @mention this agent"),
|
|
31070
|
+
latest: exports_external.coerce.number().optional().describe("Return the N most recent unread messages, newest first. Shorthand for order:desc + limit:N.")
|
|
31063
31071
|
}
|
|
31064
31072
|
}, async (args) => {
|
|
31065
31073
|
const agent = resolveIdentity(args.from);
|
|
@@ -31141,6 +31149,19 @@ server.registerTool("mark_read", {
|
|
|
31141
31149
|
content: [{ type: "text", text: JSON.stringify({ marked_read: count }) }]
|
|
31142
31150
|
};
|
|
31143
31151
|
});
|
|
31152
|
+
server.registerTool("mark_space_read", {
|
|
31153
|
+
description: "Mark ALL messages in a space as read without fetching them. Use this on busy spaces (200+ messages) where read_messages would overflow tokens.",
|
|
31154
|
+
inputSchema: {
|
|
31155
|
+
space: exports_external.string().describe("Space name"),
|
|
31156
|
+
from: exports_external.string().optional().describe("Mark read on behalf of this agent (default: current agent)")
|
|
31157
|
+
}
|
|
31158
|
+
}, async (args) => {
|
|
31159
|
+
const { space, from: fromParam } = args;
|
|
31160
|
+
const count = markSpaceRead(space, fromParam);
|
|
31161
|
+
return {
|
|
31162
|
+
content: [{ type: "text", text: JSON.stringify({ space, marked_read: count }) }]
|
|
31163
|
+
};
|
|
31164
|
+
});
|
|
31144
31165
|
server.registerTool("search_messages", {
|
|
31145
31166
|
description: "Full-text search across messages. Uses FTS5 with BM25 ranking if available, falls back to LIKE. Returns messages with snippet and relevance_score.",
|
|
31146
31167
|
inputSchema: {
|
|
@@ -31316,11 +31337,12 @@ server.registerTool("read_space", {
|
|
|
31316
31337
|
mark_read: exports_external.coerce.boolean().optional(),
|
|
31317
31338
|
max_content_length: exports_external.coerce.number().optional().describe("Truncate each message content to N chars (adds truncated:true flag)"),
|
|
31318
31339
|
threads_only: exports_external.coerce.boolean().optional().describe("Only return root messages (hides thread replies)"),
|
|
31319
|
-
include_reply_counts: exports_external.coerce.boolean().optional().describe("Include reply_count on each message")
|
|
31340
|
+
include_reply_counts: exports_external.coerce.boolean().optional().describe("Include reply_count on each message"),
|
|
31341
|
+
latest: exports_external.coerce.number().optional().describe("Return the N most recent messages, newest first")
|
|
31320
31342
|
}
|
|
31321
31343
|
}, async (args) => {
|
|
31322
|
-
const { space, since, limit, mark_read, max_content_length, threads_only, include_reply_counts } = args;
|
|
31323
|
-
const messages = readMessages({ space, since, limit, max_content_length, threads_only, include_reply_counts });
|
|
31344
|
+
const { space, since, limit, mark_read, max_content_length, threads_only, include_reply_counts, latest } = args;
|
|
31345
|
+
const messages = readMessages({ space, since, limit, max_content_length, threads_only, include_reply_counts, latest });
|
|
31324
31346
|
if (mark_read !== false && messages.length > 0) {
|
|
31325
31347
|
markReadByIds(messages.map((m) => m.id));
|
|
31326
31348
|
}
|
|
@@ -32244,6 +32266,7 @@ server.registerTool("describe_tools", {
|
|
|
32244
32266
|
list_sessions: "List all DM sessions. Optional: agent?(filter by participant)",
|
|
32245
32267
|
reply: "Reply to a specific message, creating a thread (sets reply_to). Use read_thread to retrieve. Required: message_id, content. Optional: from?",
|
|
32246
32268
|
mark_read: "Mark messages as read. Optional: from?, ids?(array), all?(bool \u2014 mark all unread)",
|
|
32269
|
+
mark_space_read: "Mark ALL messages in a space as read without fetching. Required: space. Optional: from?",
|
|
32247
32270
|
search_messages: "Full-text search messages. Required: query. Optional: space?, from?, to?, limit?",
|
|
32248
32271
|
export_messages: "Export messages as JSON or CSV. Optional: space?, session_id?, from?, since?, until?, format?(json|csv)",
|
|
32249
32272
|
create_space: "Create space and auto-join. Required: name. Optional: from?, description?, parent_id?(max 3 levels), project_id?",
|
package/dist/index.js
CHANGED
|
@@ -2369,9 +2369,10 @@ function readMessages(opts = {}) {
|
|
|
2369
2369
|
conditions.push(`id IN (SELECT message_id FROM message_mentions WHERE mentioned_agent = ?)`);
|
|
2370
2370
|
params.push(opts.mentions_only.toLowerCase());
|
|
2371
2371
|
}
|
|
2372
|
+
const isLatest = opts.latest && opts.latest > 0;
|
|
2372
2373
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
2373
|
-
const resolvedLimit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
|
|
2374
|
-
const order = opts.order?.toLowerCase() === "desc" ? "DESC" : "ASC";
|
|
2374
|
+
const resolvedLimit = isLatest ? Math.floor(opts.latest) : Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
|
|
2375
|
+
const order = isLatest ? "DESC" : opts.order?.toLowerCase() === "desc" ? "DESC" : "ASC";
|
|
2375
2376
|
const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} LIMIT ${resolvedLimit}`).all(...params);
|
|
2376
2377
|
let messages = rows.map(parseMessage);
|
|
2377
2378
|
if (opts.include_reply_counts && messages.length > 0) {
|
package/dist/types.d.ts
CHANGED