@hasna/conversations 0.2.8 → 0.2.10

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 CHANGED
@@ -2399,7 +2399,8 @@ function readMessages(opts = {}) {
2399
2399
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
2400
2400
  const resolvedLimit = isLatest ? Math.floor(opts.latest) : Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
2401
2401
  const order = isLatest ? "DESC" : opts.order?.toLowerCase() === "desc" ? "DESC" : "ASC";
2402
- const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} LIMIT ${resolvedLimit}`).all(...params);
2402
+ const resolvedOffset = opts.offset && opts.offset > 0 ? Math.floor(opts.offset) : 0;
2403
+ const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} LIMIT ${resolvedLimit} OFFSET ${resolvedOffset}`).all(...params);
2403
2404
  let messages = rows.map(parseMessage);
2404
2405
  if (opts.include_reply_counts && messages.length > 0) {
2405
2406
  const db22 = getDb();
@@ -4441,7 +4442,7 @@ var init_poll = __esm(() => {
4441
4442
  var require_package = __commonJS((exports, module) => {
4442
4443
  module.exports = {
4443
4444
  name: "@hasna/conversations",
4444
- version: "0.2.8",
4445
+ version: "0.2.10",
4445
4446
  description: "Real-time CLI messaging for AI agents",
4446
4447
  type: "module",
4447
4448
  bin: {
@@ -33698,7 +33699,8 @@ var init_mcp2 = __esm(() => {
33698
33699
  threads_only: exports_external.coerce.boolean().optional().describe("Only return root messages (reply_to IS NULL) \u2014 hides thread replies"),
33699
33700
  include_reply_counts: exports_external.coerce.boolean().optional().describe("Include reply_count on each message (adds one extra query)"),
33700
33701
  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.")
33702
+ latest: exports_external.coerce.number().optional().describe("Return the N most recent unread messages, newest first. Shorthand for order:desc + limit:N."),
33703
+ offset: exports_external.coerce.number().optional().describe("Skip first N messages for pagination (use with limit)")
33702
33704
  }
33703
33705
  }, async (args) => {
33704
33706
  const agent = resolveIdentity(args.from);
@@ -33710,7 +33712,7 @@ var init_mcp2 = __esm(() => {
33710
33712
  markReadByIds(messages.map((m) => m.id));
33711
33713
  }
33712
33714
  return {
33713
- content: [{ type: "text", text: JSON.stringify(messages) }]
33715
+ content: [{ type: "text", text: JSON.stringify({ messages, count: messages.length, offset: args.offset ?? 0 }) }]
33714
33716
  };
33715
33717
  });
33716
33718
  server.registerTool("list_sessions", {
@@ -33780,6 +33782,19 @@ var init_mcp2 = __esm(() => {
33780
33782
  content: [{ type: "text", text: JSON.stringify({ marked_read: count }) }]
33781
33783
  };
33782
33784
  });
33785
+ server.registerTool("mark_space_read", {
33786
+ 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.",
33787
+ inputSchema: {
33788
+ space: exports_external.string().describe("Space name"),
33789
+ from: exports_external.string().optional().describe("Mark read on behalf of this agent (default: current agent)")
33790
+ }
33791
+ }, async (args) => {
33792
+ const { space, from: fromParam } = args;
33793
+ const count = markSpaceRead(space, fromParam);
33794
+ return {
33795
+ content: [{ type: "text", text: JSON.stringify({ space, marked_read: count }) }]
33796
+ };
33797
+ });
33783
33798
  server.registerTool("search_messages", {
33784
33799
  description: "Full-text search across messages. Uses FTS5 with BM25 ranking if available, falls back to LIKE. Returns messages with snippet and relevance_score.",
33785
33800
  inputSchema: {
@@ -34884,6 +34899,7 @@ var init_mcp2 = __esm(() => {
34884
34899
  list_sessions: "List all DM sessions. Optional: agent?(filter by participant)",
34885
34900
  reply: "Reply to a specific message, creating a thread (sets reply_to). Use read_thread to retrieve. Required: message_id, content. Optional: from?",
34886
34901
  mark_read: "Mark messages as read. Optional: from?, ids?(array), all?(bool \u2014 mark all unread)",
34902
+ mark_space_read: "Mark ALL messages in a space as read without fetching. Required: space. Optional: from?",
34887
34903
  search_messages: "Full-text search messages. Required: query. Optional: space?, from?, to?, limit?",
34888
34904
  export_messages: "Export messages as JSON or CSV. Optional: space?, session_id?, from?, since?, until?, format?(json|csv)",
34889
34905
  create_space: "Create space and auto-join. Required: name. Optional: from?, description?, parent_id?(max 3 levels), project_id?",
package/bin/mcp.js CHANGED
@@ -28908,7 +28908,8 @@ function readMessages(opts = {}) {
28908
28908
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
28909
28909
  const resolvedLimit = isLatest ? Math.floor(opts.latest) : Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
28910
28910
  const order = isLatest ? "DESC" : opts.order?.toLowerCase() === "desc" ? "DESC" : "ASC";
28911
- const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} LIMIT ${resolvedLimit}`).all(...params);
28911
+ const resolvedOffset = opts.offset && opts.offset > 0 ? Math.floor(opts.offset) : 0;
28912
+ const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} LIMIT ${resolvedLimit} OFFSET ${resolvedOffset}`).all(...params);
28912
28913
  let messages = rows.map(parseMessage);
28913
28914
  if (opts.include_reply_counts && messages.length > 0) {
28914
28915
  const db22 = getDb();
@@ -28937,6 +28938,12 @@ function markRead(ids, reader) {
28937
28938
  const result = stmt.run(...ids, reader);
28938
28939
  return result.changes;
28939
28940
  }
28941
+ function markSpaceRead(spaceName, reader) {
28942
+ const db2 = getDb();
28943
+ 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`);
28944
+ const result = stmt.run(spaceName, reader);
28945
+ return result.changes;
28946
+ }
28940
28947
  function getMessageById(id) {
28941
28948
  const db2 = getDb();
28942
28949
  const row = db2.prepare("SELECT * FROM messages WHERE id = ?").get(id);
@@ -30925,7 +30932,7 @@ function getGraphStats() {
30925
30932
  // package.json
30926
30933
  var package_default = {
30927
30934
  name: "@hasna/conversations",
30928
- version: "0.2.8",
30935
+ version: "0.2.10",
30929
30936
  description: "Real-time CLI messaging for AI agents",
30930
30937
  type: "module",
30931
30938
  bin: {
@@ -31061,7 +31068,8 @@ server.registerTool("read_messages", {
31061
31068
  threads_only: exports_external.coerce.boolean().optional().describe("Only return root messages (reply_to IS NULL) \u2014 hides thread replies"),
31062
31069
  include_reply_counts: exports_external.coerce.boolean().optional().describe("Include reply_count on each message (adds one extra query)"),
31063
31070
  mentions_only: exports_external.string().optional().describe("Only return messages that @mention this agent"),
31064
- latest: exports_external.coerce.number().optional().describe("Return the N most recent unread messages, newest first. Shorthand for order:desc + limit:N.")
31071
+ latest: exports_external.coerce.number().optional().describe("Return the N most recent unread messages, newest first. Shorthand for order:desc + limit:N."),
31072
+ offset: exports_external.coerce.number().optional().describe("Skip first N messages for pagination (use with limit)")
31065
31073
  }
31066
31074
  }, async (args) => {
31067
31075
  const agent = resolveIdentity(args.from);
@@ -31073,7 +31081,7 @@ server.registerTool("read_messages", {
31073
31081
  markReadByIds(messages.map((m) => m.id));
31074
31082
  }
31075
31083
  return {
31076
- content: [{ type: "text", text: JSON.stringify(messages) }]
31084
+ content: [{ type: "text", text: JSON.stringify({ messages, count: messages.length, offset: args.offset ?? 0 }) }]
31077
31085
  };
31078
31086
  });
31079
31087
  server.registerTool("list_sessions", {
@@ -31143,6 +31151,19 @@ server.registerTool("mark_read", {
31143
31151
  content: [{ type: "text", text: JSON.stringify({ marked_read: count }) }]
31144
31152
  };
31145
31153
  });
31154
+ server.registerTool("mark_space_read", {
31155
+ 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.",
31156
+ inputSchema: {
31157
+ space: exports_external.string().describe("Space name"),
31158
+ from: exports_external.string().optional().describe("Mark read on behalf of this agent (default: current agent)")
31159
+ }
31160
+ }, async (args) => {
31161
+ const { space, from: fromParam } = args;
31162
+ const count = markSpaceRead(space, fromParam);
31163
+ return {
31164
+ content: [{ type: "text", text: JSON.stringify({ space, marked_read: count }) }]
31165
+ };
31166
+ });
31146
31167
  server.registerTool("search_messages", {
31147
31168
  description: "Full-text search across messages. Uses FTS5 with BM25 ranking if available, falls back to LIKE. Returns messages with snippet and relevance_score.",
31148
31169
  inputSchema: {
@@ -32247,6 +32268,7 @@ server.registerTool("describe_tools", {
32247
32268
  list_sessions: "List all DM sessions. Optional: agent?(filter by participant)",
32248
32269
  reply: "Reply to a specific message, creating a thread (sets reply_to). Use read_thread to retrieve. Required: message_id, content. Optional: from?",
32249
32270
  mark_read: "Mark messages as read. Optional: from?, ids?(array), all?(bool \u2014 mark all unread)",
32271
+ mark_space_read: "Mark ALL messages in a space as read without fetching. Required: space. Optional: from?",
32250
32272
  search_messages: "Full-text search messages. Required: query. Optional: space?, from?, to?, limit?",
32251
32273
  export_messages: "Export messages as JSON or CSV. Optional: space?, session_id?, from?, since?, until?, format?(json|csv)",
32252
32274
  create_space: "Create space and auto-join. Required: name. Optional: from?, description?, parent_id?(max 3 levels), project_id?",
package/dist/index.js CHANGED
@@ -2373,7 +2373,8 @@ function readMessages(opts = {}) {
2373
2373
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
2374
2374
  const resolvedLimit = isLatest ? Math.floor(opts.latest) : Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
2375
2375
  const order = isLatest ? "DESC" : opts.order?.toLowerCase() === "desc" ? "DESC" : "ASC";
2376
- const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} LIMIT ${resolvedLimit}`).all(...params);
2376
+ const resolvedOffset = opts.offset && opts.offset > 0 ? Math.floor(opts.offset) : 0;
2377
+ const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} LIMIT ${resolvedLimit} OFFSET ${resolvedOffset}`).all(...params);
2377
2378
  let messages = rows.map(parseMessage);
2378
2379
  if (opts.include_reply_counts && messages.length > 0) {
2379
2380
  const db22 = getDb();
package/dist/types.d.ts CHANGED
@@ -113,6 +113,7 @@ export interface ReadMessagesOptions {
113
113
  include_reply_counts?: boolean;
114
114
  mentions_only?: string;
115
115
  latest?: number;
116
+ offset?: number;
116
117
  }
117
118
  export interface SearchMessagesOptions {
118
119
  query: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/conversations",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "description": "Real-time CLI messaging for AI agents",
5
5
  "type": "module",
6
6
  "bin": {