@hasna/conversations 0.1.21 → 0.1.23

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
@@ -2822,10 +2822,6 @@ function getProjectByName(name) {
2822
2822
  }
2823
2823
  function updateProject(id, updates) {
2824
2824
  const db2 = getDb();
2825
- const existing = db2.prepare("SELECT * FROM projects WHERE id = ?").get(id);
2826
- if (!existing) {
2827
- throw new Error(`Project not found: ${id}`);
2828
- }
2829
2825
  const sets = [];
2830
2826
  const params = [];
2831
2827
  if (updates.name !== undefined) {
@@ -2861,10 +2857,15 @@ function updateProject(id, updates) {
2861
2857
  params.push(JSON.stringify(updates.settings));
2862
2858
  }
2863
2859
  if (sets.length === 0) {
2864
- return parseProject(existing);
2860
+ const row2 = db2.prepare("SELECT * FROM projects WHERE id = ?").get(id);
2861
+ if (!row2)
2862
+ throw new Error(`Project not found: ${id}`);
2863
+ return parseProject(row2);
2865
2864
  }
2866
2865
  params.push(id);
2867
2866
  const row = db2.prepare(`UPDATE projects SET ${sets.join(", ")} WHERE id = ? RETURNING *`).get(...params);
2867
+ if (!row)
2868
+ throw new Error(`Project not found: ${id}`);
2868
2869
  return parseProject(row);
2869
2870
  }
2870
2871
  function deleteProject(id) {
@@ -3313,6 +3314,7 @@ function heartbeat(agent, status, metadata) {
3313
3314
  const db2 = getDb();
3314
3315
  const metadataJson = metadata ? JSON.stringify(metadata) : null;
3315
3316
  const resolvedStatus = status || "online";
3317
+ const normalizedAgent = agent.trim().toLowerCase();
3316
3318
  db2.prepare(`
3317
3319
  INSERT INTO agent_presence (agent, status, last_seen_at, metadata)
3318
3320
  VALUES (?, ?, strftime('%Y-%m-%dT%H:%M:%f', 'now'), ?)
@@ -3320,11 +3322,12 @@ function heartbeat(agent, status, metadata) {
3320
3322
  status = excluded.status,
3321
3323
  last_seen_at = excluded.last_seen_at,
3322
3324
  metadata = excluded.metadata
3323
- `).run(agent, resolvedStatus, metadataJson);
3325
+ `).run(normalizedAgent, resolvedStatus, metadataJson);
3324
3326
  }
3325
3327
  function getPresence(agent) {
3326
3328
  const db2 = getDb();
3327
- const row = db2.prepare("SELECT * FROM agent_presence WHERE agent = ?").get(agent);
3329
+ const normalizedAgent = agent.trim().toLowerCase();
3330
+ const row = db2.prepare("SELECT * FROM agent_presence WHERE LOWER(agent) = ?").get(normalizedAgent);
3328
3331
  return row ? parsePresence(row) : null;
3329
3332
  }
3330
3333
  function listAgents(opts) {
@@ -3340,18 +3343,21 @@ function listAgents(opts) {
3340
3343
  }
3341
3344
  function removePresence(agent) {
3342
3345
  const db2 = getDb();
3343
- const result = db2.prepare("DELETE FROM agent_presence WHERE agent = ?").run(agent);
3346
+ const normalizedAgent = agent.trim().toLowerCase();
3347
+ const result = db2.prepare("DELETE FROM agent_presence WHERE LOWER(agent) = ?").run(normalizedAgent);
3344
3348
  return result.changes > 0;
3345
3349
  }
3346
3350
  function renameAgent(oldName, newName) {
3347
3351
  const db2 = getDb();
3348
- const existing = db2.prepare("SELECT agent FROM agent_presence WHERE agent = ?").get(oldName);
3352
+ const normalizedOld = oldName.trim().toLowerCase();
3353
+ const normalizedNew = newName.trim().toLowerCase();
3354
+ const existing = db2.prepare("SELECT agent FROM agent_presence WHERE LOWER(agent) = ?").get(normalizedOld);
3349
3355
  if (!existing)
3350
3356
  return false;
3351
- const conflict = db2.prepare("SELECT agent FROM agent_presence WHERE agent = ?").get(newName);
3357
+ const conflict = db2.prepare("SELECT agent FROM agent_presence WHERE LOWER(agent) = ?").get(normalizedNew);
3352
3358
  if (conflict)
3353
- throw new Error(`Agent "${newName}" already exists`);
3354
- db2.prepare("UPDATE agent_presence SET agent = ? WHERE agent = ?").run(newName, oldName);
3359
+ throw new Error(`Agent "${normalizedNew}" already exists`);
3360
+ db2.prepare("UPDATE agent_presence SET agent = ? WHERE LOWER(agent) = ?").run(normalizedNew, normalizedOld);
3355
3361
  return true;
3356
3362
  }
3357
3363
  var ONLINE_THRESHOLD_SECONDS = 60;
@@ -3503,7 +3509,7 @@ var init_poll = __esm(() => {
3503
3509
  var require_package = __commonJS((exports, module) => {
3504
3510
  module.exports = {
3505
3511
  name: "@hasna/conversations",
3506
- version: "0.1.21",
3512
+ version: "0.1.23",
3507
3513
  description: "Real-time CLI messaging for AI agents",
3508
3514
  type: "module",
3509
3515
  bin: {
@@ -30871,7 +30877,7 @@ var require_formats = __commonJS((exports) => {
30871
30877
  }
30872
30878
  var TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i;
30873
30879
  function getTime(strictTimeZone) {
30874
- return function time(str) {
30880
+ return function time3(str) {
30875
30881
  const matches = TIME.exec(str);
30876
30882
  if (!matches)
30877
30883
  return false;
@@ -32493,7 +32499,7 @@ var init_mcp2 = __esm(() => {
32493
32499
  blocking
32494
32500
  });
32495
32501
  return {
32496
- content: [{ type: "text", text: JSON.stringify(msg, null, 2) }]
32502
+ content: [{ type: "text", text: JSON.stringify(msg) }]
32497
32503
  };
32498
32504
  });
32499
32505
  server.registerTool("read_messages", {
@@ -32510,7 +32516,7 @@ var init_mcp2 = __esm(() => {
32510
32516
  }, async (args) => {
32511
32517
  const messages = readMessages(args);
32512
32518
  return {
32513
- content: [{ type: "text", text: JSON.stringify(messages, null, 2) }]
32519
+ content: [{ type: "text", text: JSON.stringify(messages) }]
32514
32520
  };
32515
32521
  });
32516
32522
  server.registerTool("list_sessions", {
@@ -32522,7 +32528,7 @@ var init_mcp2 = __esm(() => {
32522
32528
  const { agent } = args;
32523
32529
  const sessions = listSessions(agent);
32524
32530
  return {
32525
- content: [{ type: "text", text: JSON.stringify(sessions, null, 2) }]
32531
+ content: [{ type: "text", text: JSON.stringify(sessions) }]
32526
32532
  };
32527
32533
  });
32528
32534
  server.registerTool("reply", {
@@ -32552,7 +32558,7 @@ var init_mcp2 = __esm(() => {
32552
32558
  space
32553
32559
  });
32554
32560
  return {
32555
- content: [{ type: "text", text: JSON.stringify(msg, null, 2) }]
32561
+ content: [{ type: "text", text: JSON.stringify(msg) }]
32556
32562
  };
32557
32563
  });
32558
32564
  server.registerTool("mark_read", {
@@ -32577,7 +32583,7 @@ var init_mcp2 = __esm(() => {
32577
32583
  };
32578
32584
  }
32579
32585
  return {
32580
- content: [{ type: "text", text: JSON.stringify({ marked_read: count }, null, 2) }]
32586
+ content: [{ type: "text", text: JSON.stringify({ marked_read: count }) }]
32581
32587
  };
32582
32588
  });
32583
32589
  server.registerTool("search_messages", {
@@ -32593,7 +32599,7 @@ var init_mcp2 = __esm(() => {
32593
32599
  const { query, space, from, to, limit } = args;
32594
32600
  const messages = searchMessages({ query, space, from, to, limit });
32595
32601
  return {
32596
- content: [{ type: "text", text: JSON.stringify(messages, null, 2) }]
32602
+ content: [{ type: "text", text: JSON.stringify(messages) }]
32597
32603
  };
32598
32604
  });
32599
32605
  server.registerTool("export_messages", {
@@ -32628,7 +32634,7 @@ var init_mcp2 = __esm(() => {
32628
32634
  try {
32629
32635
  const sp = createSpace(name, agent, { description, parent_id, project_id });
32630
32636
  return {
32631
- content: [{ type: "text", text: JSON.stringify(sp, null, 2) }]
32637
+ content: [{ type: "text", text: JSON.stringify(sp) }]
32632
32638
  };
32633
32639
  } catch (e) {
32634
32640
  if (e.message?.includes("UNIQUE constraint")) {
@@ -32664,7 +32670,7 @@ var init_mcp2 = __esm(() => {
32664
32670
  opts.include_archived = true;
32665
32671
  const spaces = listSpaces(opts);
32666
32672
  return {
32667
- content: [{ type: "text", text: JSON.stringify(spaces, null, 2) }]
32673
+ content: [{ type: "text", text: JSON.stringify(spaces) }]
32668
32674
  };
32669
32675
  });
32670
32676
  server.registerTool("send_to_space", {
@@ -32696,7 +32702,7 @@ var init_mcp2 = __esm(() => {
32696
32702
  blocking
32697
32703
  });
32698
32704
  return {
32699
- content: [{ type: "text", text: JSON.stringify(msg, null, 2) }]
32705
+ content: [{ type: "text", text: JSON.stringify(msg) }]
32700
32706
  };
32701
32707
  });
32702
32708
  server.registerTool("read_space", {
@@ -32710,7 +32716,7 @@ var init_mcp2 = __esm(() => {
32710
32716
  const { space, since, limit } = args;
32711
32717
  const messages = readMessages({ space, since, limit });
32712
32718
  return {
32713
- content: [{ type: "text", text: JSON.stringify(messages, null, 2) }]
32719
+ content: [{ type: "text", text: JSON.stringify(messages) }]
32714
32720
  };
32715
32721
  });
32716
32722
  server.registerTool("join_space", {
@@ -32730,7 +32736,7 @@ var init_mcp2 = __esm(() => {
32730
32736
  };
32731
32737
  }
32732
32738
  return {
32733
- content: [{ type: "text", text: JSON.stringify({ space, agent, joined: true }, null, 2) }]
32739
+ content: [{ type: "text", text: JSON.stringify({ space, agent, joined: true }) }]
32734
32740
  };
32735
32741
  });
32736
32742
  server.registerTool("leave_space", {
@@ -32744,7 +32750,7 @@ var init_mcp2 = __esm(() => {
32744
32750
  const agent = resolveIdentity(fromParam);
32745
32751
  const left = leaveSpace(space, agent);
32746
32752
  return {
32747
- content: [{ type: "text", text: JSON.stringify({ space, agent, left }, null, 2) }]
32753
+ content: [{ type: "text", text: JSON.stringify({ space, agent, left }) }]
32748
32754
  };
32749
32755
  });
32750
32756
  server.registerTool("update_space", {
@@ -32767,7 +32773,7 @@ var init_mcp2 = __esm(() => {
32767
32773
  try {
32768
32774
  const sp = updateSpace(name, updates);
32769
32775
  return {
32770
- content: [{ type: "text", text: JSON.stringify(sp, null, 2) }]
32776
+ content: [{ type: "text", text: JSON.stringify(sp) }]
32771
32777
  };
32772
32778
  } catch (e) {
32773
32779
  return {
@@ -32785,7 +32791,7 @@ var init_mcp2 = __esm(() => {
32785
32791
  try {
32786
32792
  const sp = archiveSpace(name);
32787
32793
  return {
32788
- content: [{ type: "text", text: JSON.stringify(sp, null, 2) }]
32794
+ content: [{ type: "text", text: JSON.stringify(sp) }]
32789
32795
  };
32790
32796
  } catch (e) {
32791
32797
  return {
@@ -32803,7 +32809,7 @@ var init_mcp2 = __esm(() => {
32803
32809
  try {
32804
32810
  const sp = unarchiveSpace(name);
32805
32811
  return {
32806
- content: [{ type: "text", text: JSON.stringify(sp, null, 2) }]
32812
+ content: [{ type: "text", text: JSON.stringify(sp) }]
32807
32813
  };
32808
32814
  } catch (e) {
32809
32815
  return {
@@ -32872,7 +32878,7 @@ var init_mcp2 = __esm(() => {
32872
32878
  settings: parsedSettings
32873
32879
  });
32874
32880
  return {
32875
- content: [{ type: "text", text: JSON.stringify(project, null, 2) }]
32881
+ content: [{ type: "text", text: JSON.stringify(project) }]
32876
32882
  };
32877
32883
  } catch (e) {
32878
32884
  if (e.message?.includes("UNIQUE constraint")) {
@@ -32896,7 +32902,7 @@ var init_mcp2 = __esm(() => {
32896
32902
  const { status } = args;
32897
32903
  const projects = listProjects(status ? { status } : undefined);
32898
32904
  return {
32899
- content: [{ type: "text", text: JSON.stringify(projects, null, 2) }]
32905
+ content: [{ type: "text", text: JSON.stringify(projects) }]
32900
32906
  };
32901
32907
  });
32902
32908
  server.registerTool("get_project", {
@@ -32916,7 +32922,7 @@ var init_mcp2 = __esm(() => {
32916
32922
  };
32917
32923
  }
32918
32924
  return {
32919
- content: [{ type: "text", text: JSON.stringify(project, null, 2) }]
32925
+ content: [{ type: "text", text: JSON.stringify(project) }]
32920
32926
  };
32921
32927
  });
32922
32928
  server.registerTool("update_project", {
@@ -32978,7 +32984,7 @@ var init_mcp2 = __esm(() => {
32978
32984
  try {
32979
32985
  const project = updateProject(id, updates);
32980
32986
  return {
32981
- content: [{ type: "text", text: JSON.stringify(project, null, 2) }]
32987
+ content: [{ type: "text", text: JSON.stringify(project) }]
32982
32988
  };
32983
32989
  } catch (e) {
32984
32990
  return {
@@ -33002,7 +33008,7 @@ var init_mcp2 = __esm(() => {
33002
33008
  };
33003
33009
  }
33004
33010
  return {
33005
- content: [{ type: "text", text: JSON.stringify({ id, deleted: true }, null, 2) }]
33011
+ content: [{ type: "text", text: JSON.stringify({ id, deleted: true }) }]
33006
33012
  };
33007
33013
  } catch (e) {
33008
33014
  return {
@@ -33028,7 +33034,7 @@ var init_mcp2 = __esm(() => {
33028
33034
  };
33029
33035
  }
33030
33036
  return {
33031
- content: [{ type: "text", text: JSON.stringify({ deleted: true }, null, 2) }]
33037
+ content: [{ type: "text", text: JSON.stringify({ deleted: true }) }]
33032
33038
  };
33033
33039
  });
33034
33040
  server.registerTool("edit_message", {
@@ -33049,7 +33055,7 @@ var init_mcp2 = __esm(() => {
33049
33055
  };
33050
33056
  }
33051
33057
  return {
33052
- content: [{ type: "text", text: JSON.stringify(msg, null, 2) }]
33058
+ content: [{ type: "text", text: JSON.stringify(msg) }]
33053
33059
  };
33054
33060
  });
33055
33061
  server.registerTool("pin_message", {
@@ -33066,7 +33072,7 @@ var init_mcp2 = __esm(() => {
33066
33072
  };
33067
33073
  }
33068
33074
  return {
33069
- content: [{ type: "text", text: JSON.stringify(msg, null, 2) }]
33075
+ content: [{ type: "text", text: JSON.stringify(msg) }]
33070
33076
  };
33071
33077
  });
33072
33078
  server.registerTool("unpin_message", {
@@ -33083,7 +33089,7 @@ var init_mcp2 = __esm(() => {
33083
33089
  };
33084
33090
  }
33085
33091
  return {
33086
- content: [{ type: "text", text: JSON.stringify(msg, null, 2) }]
33092
+ content: [{ type: "text", text: JSON.stringify(msg) }]
33087
33093
  };
33088
33094
  });
33089
33095
  server.registerTool("get_pinned_messages", {
@@ -33097,7 +33103,7 @@ var init_mcp2 = __esm(() => {
33097
33103
  const { space, session_id, limit } = args;
33098
33104
  const messages = getPinnedMessages({ space, session_id, limit });
33099
33105
  return {
33100
- content: [{ type: "text", text: JSON.stringify(messages, null, 2) }]
33106
+ content: [{ type: "text", text: JSON.stringify(messages) }]
33101
33107
  };
33102
33108
  });
33103
33109
  server.registerTool("heartbeat", {
@@ -33111,7 +33117,7 @@ var init_mcp2 = __esm(() => {
33111
33117
  const agent = resolveIdentity(fromParam);
33112
33118
  heartbeat(agent, status);
33113
33119
  return {
33114
- content: [{ type: "text", text: JSON.stringify({ agent, status: status || "online", heartbeat: true }, null, 2) }]
33120
+ content: [{ type: "text", text: JSON.stringify({ agent, status: status || "online", heartbeat: true }) }]
33115
33121
  };
33116
33122
  });
33117
33123
  server.registerTool("list_agents", {
@@ -33123,7 +33129,7 @@ var init_mcp2 = __esm(() => {
33123
33129
  const { online_only } = args;
33124
33130
  const agents = listAgents({ online_only });
33125
33131
  return {
33126
- content: [{ type: "text", text: JSON.stringify(agents, null, 2) }]
33132
+ content: [{ type: "text", text: JSON.stringify(agents) }]
33127
33133
  };
33128
33134
  });
33129
33135
  server.registerTool("get_blockers", {
@@ -33136,7 +33142,7 @@ var init_mcp2 = __esm(() => {
33136
33142
  const agent = resolveIdentity(fromParam);
33137
33143
  const blockers = getUnreadBlockers(agent);
33138
33144
  return {
33139
- content: [{ type: "text", text: JSON.stringify(blockers, null, 2) }]
33145
+ content: [{ type: "text", text: JSON.stringify(blockers) }]
33140
33146
  };
33141
33147
  });
33142
33148
  server.registerTool("remove_agent", {
@@ -33157,7 +33163,7 @@ var init_mcp2 = __esm(() => {
33157
33163
  };
33158
33164
  }
33159
33165
  return {
33160
- content: [{ type: "text", text: JSON.stringify({ agent, removed: true }, null, 2) }]
33166
+ content: [{ type: "text", text: JSON.stringify({ agent, removed: true }) }]
33161
33167
  };
33162
33168
  });
33163
33169
  server.registerTool("rename_agent", {
@@ -33185,7 +33191,7 @@ var init_mcp2 = __esm(() => {
33185
33191
  };
33186
33192
  }
33187
33193
  return {
33188
- content: [{ type: "text", text: JSON.stringify({ old_name: oldName, new_name: newName, renamed: true }, null, 2) }]
33194
+ content: [{ type: "text", text: JSON.stringify({ old_name: oldName, new_name: newName, renamed: true }) }]
33189
33195
  };
33190
33196
  } catch (e) {
33191
33197
  return {
@@ -33320,6 +33326,33 @@ function securityHeaders(base) {
33320
33326
  }
33321
33327
  return headers;
33322
33328
  }
33329
+ function applyFields(data, fields) {
33330
+ if (!fields)
33331
+ return data;
33332
+ const keys = fields.split(",").map((s) => s.trim()).filter(Boolean);
33333
+ if (!keys.length)
33334
+ return data;
33335
+ if (Array.isArray(data)) {
33336
+ return data.map((item) => {
33337
+ if (item && typeof item === "object") {
33338
+ const out = {};
33339
+ for (const k of keys)
33340
+ if (k in item)
33341
+ out[k] = item[k];
33342
+ return out;
33343
+ }
33344
+ return item;
33345
+ });
33346
+ }
33347
+ if (data && typeof data === "object") {
33348
+ const out = {};
33349
+ for (const k of keys)
33350
+ if (k in data)
33351
+ out[k] = data[k];
33352
+ return out;
33353
+ }
33354
+ return data;
33355
+ }
33323
33356
  function jsonResponse(data, status = 200) {
33324
33357
  return new Response(JSON.stringify(data), {
33325
33358
  status,
@@ -33392,8 +33425,9 @@ function startDashboardServer(port = 0, host) {
33392
33425
  const space = url2.searchParams.get("space") || undefined;
33393
33426
  const from = url2.searchParams.get("from") || undefined;
33394
33427
  const to = url2.searchParams.get("to") || undefined;
33395
- const messages = readMessages({ session_id: session, space, from, to, limit, order: "desc" });
33396
- return jsonResponse(messages);
33428
+ const compact = url2.searchParams.get("compact") === "true";
33429
+ const messages = readMessages({ session_id: session, space, from, to, limit, order: "desc", compact });
33430
+ return jsonResponse(applyFields(messages, url2.searchParams.get("fields")));
33397
33431
  }
33398
33432
  if (path === "/api/messages" && req.method === "POST") {
33399
33433
  if (!isSameOrigin(req)) {
@@ -33538,7 +33572,7 @@ function startDashboardServer(port = 0, host) {
33538
33572
  }
33539
33573
  if (path === "/api/sessions") {
33540
33574
  const agent = url2.searchParams.get("agent") || undefined;
33541
- return jsonResponse(listSessions(agent));
33575
+ return jsonResponse(applyFields(listSessions(agent), url2.searchParams.get("fields")));
33542
33576
  }
33543
33577
  if (path === "/api/spaces" && req.method === "GET") {
33544
33578
  const projectId = url2.searchParams.get("project_id") || undefined;
@@ -33548,7 +33582,7 @@ function startDashboardServer(port = 0, host) {
33548
33582
  listOpts.project_id = projectId;
33549
33583
  if (includeArchived)
33550
33584
  listOpts.include_archived = true;
33551
- return jsonResponse(listSpaces(Object.keys(listOpts).length > 0 ? listOpts : undefined));
33585
+ return jsonResponse(applyFields(listSpaces(Object.keys(listOpts).length > 0 ? listOpts : undefined), url2.searchParams.get("fields")));
33552
33586
  }
33553
33587
  if (path === "/api/spaces" && req.method === "POST") {
33554
33588
  if (!isSameOrigin(req)) {
@@ -33627,7 +33661,7 @@ function startDashboardServer(port = 0, host) {
33627
33661
  }
33628
33662
  if (path === "/api/projects" && req.method === "GET") {
33629
33663
  const status = url2.searchParams.get("status");
33630
- return jsonResponse(listProjects(status ? { status } : undefined));
33664
+ return jsonResponse(applyFields(listProjects(status ? { status } : undefined), url2.searchParams.get("fields")));
33631
33665
  }
33632
33666
  if (path === "/api/projects" && req.method === "POST") {
33633
33667
  if (!isSameOrigin(req)) {
@@ -33697,7 +33731,7 @@ function startDashboardServer(port = 0, host) {
33697
33731
  if (path === "/api/agents" && req.method === "GET") {
33698
33732
  const onlineOnly = url2.searchParams.get("online_only") === "true";
33699
33733
  const agents = listAgents({ online_only: onlineOnly });
33700
- return jsonResponse(agents);
33734
+ return jsonResponse(applyFields(agents, url2.searchParams.get("fields")));
33701
33735
  }
33702
33736
  if (path === "/api/version" && req.method === "GET") {
33703
33737
  try {