@hasna/conversations 0.1.3 → 0.1.5

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
@@ -2619,7 +2619,381 @@ var init_projects = __esm(() => {
2619
2619
  init_db();
2620
2620
  });
2621
2621
 
2622
+ // src/lib/names.ts
2623
+ var AGENT_NAMES;
2624
+ var init_names = __esm(() => {
2625
+ AGENT_NAMES = [
2626
+ "amber-fox",
2627
+ "arctic-wolf",
2628
+ "ashen-crow",
2629
+ "azure-hawk",
2630
+ "astral-lynx",
2631
+ "autumn-bear",
2632
+ "agile-puma",
2633
+ "alpine-ibex",
2634
+ "ancient-owl",
2635
+ "aqua-otter",
2636
+ "arid-viper",
2637
+ "atom-finch",
2638
+ "auburn-deer",
2639
+ "aurora-seal",
2640
+ "avid-mink",
2641
+ "blaze-tiger",
2642
+ "bright-heron",
2643
+ "bronze-eagle",
2644
+ "brisk-hare",
2645
+ "burnt-moth",
2646
+ "bold-raven",
2647
+ "blue-whale",
2648
+ "boreal-fox",
2649
+ "brass-cobra",
2650
+ "brave-ram",
2651
+ "brick-crane",
2652
+ "brief-newt",
2653
+ "briny-crab",
2654
+ "broad-elk",
2655
+ "brook-dove",
2656
+ "calm-panda",
2657
+ "cedar-jay",
2658
+ "chief-lion",
2659
+ "chrome-bat",
2660
+ "civic-wren",
2661
+ "clear-swan",
2662
+ "cliff-goat",
2663
+ "coal-shark",
2664
+ "cold-crane",
2665
+ "copper-jay",
2666
+ "coral-fish",
2667
+ "crisp-lark",
2668
+ "cross-mole",
2669
+ "cubic-wasp",
2670
+ "cyan-toad",
2671
+ "dark-stag",
2672
+ "dawn-robin",
2673
+ "deep-squid",
2674
+ "delta-fox",
2675
+ "dense-boar",
2676
+ "dew-spider",
2677
+ "dim-gecko",
2678
+ "draft-bear",
2679
+ "drift-gull",
2680
+ "dry-newt",
2681
+ "dual-crane",
2682
+ "dune-mouse",
2683
+ "dusk-moth",
2684
+ "dusty-mule",
2685
+ "dwarf-carp",
2686
+ "east-falcon",
2687
+ "echo-parrot",
2688
+ "edge-shark",
2689
+ "elm-beetle",
2690
+ "ember-lynx",
2691
+ "epoch-crane",
2692
+ "even-pike",
2693
+ "extra-ant",
2694
+ "elder-stork",
2695
+ "ebon-crow",
2696
+ "ever-finch",
2697
+ "exact-moth",
2698
+ "exile-wren",
2699
+ "equal-dove",
2700
+ "etch-hare",
2701
+ "faint-orca",
2702
+ "far-condor",
2703
+ "fern-mouse",
2704
+ "fierce-yak",
2705
+ "first-kite",
2706
+ "fjord-seal",
2707
+ "flint-wolf",
2708
+ "fog-parrot",
2709
+ "forge-bull",
2710
+ "fossil-ray",
2711
+ "frank-mink",
2712
+ "free-eagle",
2713
+ "fresh-colt",
2714
+ "frost-bear",
2715
+ "fuse-wasp",
2716
+ "gale-hawk",
2717
+ "gem-turtle",
2718
+ "ghost-lynx",
2719
+ "gilt-robin",
2720
+ "glad-moose",
2721
+ "glass-eel",
2722
+ "gleam-puma",
2723
+ "glyph-owl",
2724
+ "gold-crane",
2725
+ "gorge-lion",
2726
+ "grain-duck",
2727
+ "grand-wolf",
2728
+ "gray-fox",
2729
+ "green-hare",
2730
+ "grit-shark",
2731
+ "half-stork",
2732
+ "haze-panther",
2733
+ "heart-dove",
2734
+ "helm-eagle",
2735
+ "herb-toad",
2736
+ "hex-spider",
2737
+ "high-falcon",
2738
+ "hive-hornet",
2739
+ "holo-swan",
2740
+ "hood-cobra",
2741
+ "horn-bison",
2742
+ "huge-squid",
2743
+ "hull-crab",
2744
+ "hunt-marten",
2745
+ "husk-moth",
2746
+ "ice-leopard",
2747
+ "idle-crane",
2748
+ "inch-beetle",
2749
+ "indigo-jay",
2750
+ "inner-fox",
2751
+ "ion-parrot",
2752
+ "iron-bull",
2753
+ "isle-pelican",
2754
+ "ivory-hawk",
2755
+ "ivy-snake",
2756
+ "iota-wren",
2757
+ "ink-raven",
2758
+ "ignite-ram",
2759
+ "inert-slug",
2760
+ "infra-mole",
2761
+ "jade-tiger",
2762
+ "jest-magpie",
2763
+ "jewel-crane",
2764
+ "joint-boar",
2765
+ "jovial-elk",
2766
+ "jump-frog",
2767
+ "jungle-cat",
2768
+ "jury-dove",
2769
+ "just-heron",
2770
+ "jolt-wasp",
2771
+ "keen-osprey",
2772
+ "kelp-seal",
2773
+ "key-falcon",
2774
+ "kind-panda",
2775
+ "knot-viper",
2776
+ "kraft-bear",
2777
+ "kite-mouse",
2778
+ "knoll-deer",
2779
+ "know-crane",
2780
+ "karma-wolf",
2781
+ "lake-otter",
2782
+ "lapis-jay",
2783
+ "last-condor",
2784
+ "leaf-gecko",
2785
+ "lean-coyote",
2786
+ "light-lynx",
2787
+ "lime-parrot",
2788
+ "live-eagle",
2789
+ "long-crane",
2790
+ "lost-fox",
2791
+ "loud-finch",
2792
+ "low-shark",
2793
+ "luck-rabbit",
2794
+ "lunar-owl",
2795
+ "lush-ibis",
2796
+ "malt-badger",
2797
+ "maple-wren",
2798
+ "mars-falcon",
2799
+ "matte-crow",
2800
+ "mesa-hawk",
2801
+ "mild-orca",
2802
+ "mint-dove",
2803
+ "mist-puma",
2804
+ "mock-robin",
2805
+ "mono-wolf",
2806
+ "moon-bear",
2807
+ "moss-turtle",
2808
+ "mud-heron",
2809
+ "mute-swan",
2810
+ "myth-lynx",
2811
+ "navy-eagle",
2812
+ "near-mink",
2813
+ "neon-parrot",
2814
+ "nest-crane",
2815
+ "next-fox",
2816
+ "nimble-ram",
2817
+ "node-spider",
2818
+ "noon-hawk",
2819
+ "north-seal",
2820
+ "nova-owl",
2821
+ "null-moth",
2822
+ "numb-carp",
2823
+ "nutmeg-jay",
2824
+ "neat-cobra",
2825
+ "nomad-elk",
2826
+ "oak-badger",
2827
+ "oat-finch",
2828
+ "odd-pelican",
2829
+ "olive-bear",
2830
+ "onyx-raven",
2831
+ "opal-crane",
2832
+ "open-wolf",
2833
+ "orbit-lynx",
2834
+ "ore-shark",
2835
+ "outer-dove",
2836
+ "pale-tiger",
2837
+ "park-heron",
2838
+ "peak-eagle",
2839
+ "pine-fox",
2840
+ "pixel-owl",
2841
+ "plain-goat",
2842
+ "plum-crane",
2843
+ "polar-ray",
2844
+ "port-falcon",
2845
+ "prime-wolf",
2846
+ "prism-jay",
2847
+ "proud-lion",
2848
+ "pulse-bat",
2849
+ "pure-swan",
2850
+ "pyro-hawk",
2851
+ "quake-bear",
2852
+ "quartz-jay",
2853
+ "quest-falcon",
2854
+ "quick-otter",
2855
+ "quiet-crane",
2856
+ "rain-leopard",
2857
+ "rapid-hare",
2858
+ "raw-condor",
2859
+ "reef-dolphin",
2860
+ "regal-stag",
2861
+ "ridge-fox",
2862
+ "rift-cobra",
2863
+ "rigid-crane",
2864
+ "river-otter",
2865
+ "rock-eagle",
2866
+ "root-mole",
2867
+ "rose-finch",
2868
+ "rough-boar",
2869
+ "ruby-hawk",
2870
+ "rust-wolf",
2871
+ "sage-owl",
2872
+ "salt-crane",
2873
+ "sand-viper",
2874
+ "satin-dove",
2875
+ "scale-dragon",
2876
+ "scarlet-ibis",
2877
+ "sea-falcon",
2878
+ "shade-lynx",
2879
+ "sharp-eagle",
2880
+ "shell-crab",
2881
+ "short-fox",
2882
+ "sigma-jay",
2883
+ "silk-moth",
2884
+ "silver-wolf",
2885
+ "slate-bear",
2886
+ "slim-heron",
2887
+ "smoke-puma",
2888
+ "snap-turtle",
2889
+ "snow-leopard",
2890
+ "solar-crane",
2891
+ "solid-ram",
2892
+ "sonic-bat",
2893
+ "south-seal",
2894
+ "spark-robin",
2895
+ "spice-wren",
2896
+ "split-mink",
2897
+ "spring-elk",
2898
+ "squid-ink",
2899
+ "stark-crow",
2900
+ "steel-hawk",
2901
+ "stern-bull",
2902
+ "still-swan",
2903
+ "stone-fox",
2904
+ "storm-eagle",
2905
+ "stout-boar",
2906
+ "stray-cat",
2907
+ "strong-lion",
2908
+ "sun-parrot",
2909
+ "surf-dolphin",
2910
+ "swift-deer",
2911
+ "teal-crane",
2912
+ "terra-wolf",
2913
+ "thick-bear",
2914
+ "thin-spider",
2915
+ "third-owl",
2916
+ "thorn-fox",
2917
+ "tide-seal",
2918
+ "timber-jay",
2919
+ "tiny-wren",
2920
+ "toast-mole",
2921
+ "topaz-hawk",
2922
+ "torch-lynx",
2923
+ "trace-falcon",
2924
+ "true-eagle",
2925
+ "tusk-walrus",
2926
+ "ultra-crane",
2927
+ "umbra-wolf",
2928
+ "unit-fox",
2929
+ "upper-hawk",
2930
+ "urban-jay",
2931
+ "vale-deer",
2932
+ "vast-eagle",
2933
+ "vault-bear",
2934
+ "velvet-owl",
2935
+ "vent-crane",
2936
+ "verse-fox",
2937
+ "vigor-lynx",
2938
+ "vine-parrot",
2939
+ "vivid-swan",
2940
+ "void-raven",
2941
+ "volt-hawk",
2942
+ "vow-falcon",
2943
+ "vintage-jay",
2944
+ "vista-wolf",
2945
+ "vital-hare",
2946
+ "warm-otter",
2947
+ "wave-dolphin",
2948
+ "wax-crane",
2949
+ "west-falcon",
2950
+ "wheat-mouse",
2951
+ "white-tiger",
2952
+ "wide-eagle",
2953
+ "wild-fox",
2954
+ "wind-hawk",
2955
+ "wire-spider",
2956
+ "wise-owl",
2957
+ "wood-thrush",
2958
+ "wool-ram",
2959
+ "wren-song",
2960
+ "wry-crow",
2961
+ "xeno-crane",
2962
+ "xerus-fox",
2963
+ "yarn-robin",
2964
+ "yew-falcon",
2965
+ "young-wolf",
2966
+ "zeal-hawk",
2967
+ "zen-panda",
2968
+ "zero-crane",
2969
+ "zinc-eagle",
2970
+ "zone-fox"
2971
+ ];
2972
+ });
2973
+
2622
2974
  // src/lib/identity.ts
2975
+ import { readFileSync, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
2976
+ import { join as join2, dirname as dirname2 } from "path";
2977
+ import { homedir as homedir2 } from "os";
2978
+ function getAutoName() {
2979
+ if (cachedAutoName)
2980
+ return cachedAutoName;
2981
+ try {
2982
+ const name2 = readFileSync(AGENT_ID_FILE, "utf-8").trim();
2983
+ if (name2) {
2984
+ cachedAutoName = name2;
2985
+ return name2;
2986
+ }
2987
+ } catch {}
2988
+ const name = AGENT_NAMES[Math.floor(Math.random() * AGENT_NAMES.length)];
2989
+ cachedAutoName = name;
2990
+ try {
2991
+ mkdirSync2(dirname2(AGENT_ID_FILE), { recursive: true });
2992
+ writeFileSync(AGENT_ID_FILE, name + `
2993
+ `, "utf-8");
2994
+ } catch {}
2995
+ return name;
2996
+ }
2623
2997
  function resolveIdentity(explicit) {
2624
2998
  const explicitValue = explicit?.trim();
2625
2999
  if (explicitValue)
@@ -2627,8 +3001,13 @@ function resolveIdentity(explicit) {
2627
3001
  const envValue = process.env.CONVERSATIONS_AGENT_ID?.trim();
2628
3002
  if (envValue)
2629
3003
  return envValue;
2630
- return "user";
3004
+ return getAutoName();
2631
3005
  }
3006
+ var AGENT_ID_FILE, cachedAutoName = null;
3007
+ var init_identity = __esm(() => {
3008
+ init_names();
3009
+ AGENT_ID_FILE = join2(homedir2(), ".conversations", "agent-id");
3010
+ });
2632
3011
 
2633
3012
  // src/lib/presence.ts
2634
3013
  function parsePresence(row) {
@@ -2676,6 +3055,22 @@ function listAgents(opts) {
2676
3055
  const rows = db2.prepare(query).all(...params);
2677
3056
  return rows.map(parsePresence);
2678
3057
  }
3058
+ function removePresence(agent) {
3059
+ const db2 = getDb();
3060
+ const result = db2.prepare("DELETE FROM agent_presence WHERE agent = ?").run(agent);
3061
+ return result.changes > 0;
3062
+ }
3063
+ function renameAgent(oldName, newName) {
3064
+ const db2 = getDb();
3065
+ const existing = db2.prepare("SELECT agent FROM agent_presence WHERE agent = ?").get(oldName);
3066
+ if (!existing)
3067
+ return false;
3068
+ const conflict = db2.prepare("SELECT agent FROM agent_presence WHERE agent = ?").get(newName);
3069
+ if (conflict)
3070
+ throw new Error(`Agent "${newName}" already exists`);
3071
+ db2.prepare("UPDATE agent_presence SET agent = ? WHERE agent = ?").run(newName, oldName);
3072
+ return true;
3073
+ }
2679
3074
  var ONLINE_THRESHOLD_SECONDS = 60;
2680
3075
  var init_presence = __esm(() => {
2681
3076
  init_db();
@@ -2685,7 +3080,7 @@ var init_presence = __esm(() => {
2685
3080
  var require_package = __commonJS((exports, module) => {
2686
3081
  module.exports = {
2687
3082
  name: "@hasna/conversations",
2688
- version: "0.1.3",
3083
+ version: "0.1.5",
2689
3084
  description: "Real-time CLI messaging for AI agents",
2690
3085
  type: "module",
2691
3086
  bin: {
@@ -31643,6 +32038,7 @@ var init_mcp2 = __esm(() => {
31643
32038
  init_sessions();
31644
32039
  init_spaces();
31645
32040
  init_projects();
32041
+ init_identity();
31646
32042
  init_presence();
31647
32043
  import__package = __toESM(require_package(), 1);
31648
32044
  server = new McpServer({
@@ -32328,6 +32724,61 @@ var init_mcp2 = __esm(() => {
32328
32724
  content: [{ type: "text", text: JSON.stringify(agents, null, 2) }]
32329
32725
  };
32330
32726
  });
32727
+ server.registerTool("remove_agent", {
32728
+ title: "Remove Agent",
32729
+ description: "Remove an agent from the presence list. Only the agent itself should remove its own presence.",
32730
+ inputSchema: {
32731
+ from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
32732
+ agent: exports_external.string().optional().describe("Agent to remove (defaults to yourself)")
32733
+ }
32734
+ }, async ({ from: fromParam, agent: targetAgent }) => {
32735
+ const self = resolveIdentity(fromParam);
32736
+ const agent = targetAgent?.trim() || self;
32737
+ const removed = removePresence(agent);
32738
+ if (!removed) {
32739
+ return {
32740
+ content: [{ type: "text", text: `Agent "${agent}" not found` }],
32741
+ isError: true
32742
+ };
32743
+ }
32744
+ return {
32745
+ content: [{ type: "text", text: JSON.stringify({ agent, removed: true }, null, 2) }]
32746
+ };
32747
+ });
32748
+ server.registerTool("rename_agent", {
32749
+ title: "Rename Agent",
32750
+ description: "Rename an agent in the presence list. By default renames yourself.",
32751
+ inputSchema: {
32752
+ from: exports_external.string().optional().describe("Your current agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
32753
+ new_name: exports_external.string().describe("The new name for the agent")
32754
+ }
32755
+ }, async ({ from: fromParam, new_name }) => {
32756
+ const oldName = resolveIdentity(fromParam);
32757
+ const newName = new_name.trim();
32758
+ if (!newName) {
32759
+ return {
32760
+ content: [{ type: "text", text: "New name cannot be empty" }],
32761
+ isError: true
32762
+ };
32763
+ }
32764
+ try {
32765
+ const renamed = renameAgent(oldName, newName);
32766
+ if (!renamed) {
32767
+ return {
32768
+ content: [{ type: "text", text: `Agent "${oldName}" not found in presence list` }],
32769
+ isError: true
32770
+ };
32771
+ }
32772
+ return {
32773
+ content: [{ type: "text", text: JSON.stringify({ old_name: oldName, new_name: newName, renamed: true }, null, 2) }]
32774
+ };
32775
+ } catch (e) {
32776
+ return {
32777
+ content: [{ type: "text", text: e.message }],
32778
+ isError: true
32779
+ };
32780
+ }
32781
+ });
32331
32782
  isDirectRun = import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith("mcp.js") || process.argv[1]?.endsWith("mcp.ts");
32332
32783
  if (isDirectRun) {
32333
32784
  startMcpServer().catch((error48) => {
@@ -32342,7 +32793,7 @@ var exports_serve = {};
32342
32793
  __export(exports_serve, {
32343
32794
  startDashboardServer: () => startDashboardServer
32344
32795
  });
32345
- import { join as join2, resolve, sep } from "path";
32796
+ import { join as join3, resolve, sep } from "path";
32346
32797
  import { existsSync } from "fs";
32347
32798
  function securityHeaders(base) {
32348
32799
  const headers = new Headers(base);
@@ -32413,7 +32864,7 @@ function isSameOrigin(req) {
32413
32864
  function startDashboardServer(port = 3456, host) {
32414
32865
  const resolvedPort = normalizePort(port, 3456);
32415
32866
  const resolvedHost = normalizeHost(host ?? process.env.CONVERSATIONS_DASHBOARD_HOST);
32416
- const dashboardDist = join2(import.meta.dir, "../../dashboard/dist");
32867
+ const dashboardDist = join3(import.meta.dir, "../../dashboard/dist");
32417
32868
  const hasDist = existsSync(dashboardDist);
32418
32869
  const server2 = Bun.serve({
32419
32870
  port: resolvedPort,
@@ -32797,7 +33248,7 @@ function startDashboardServer(port = 3456, host) {
32797
33248
  headers.set("Content-Type", file2.type);
32798
33249
  return new Response(file2, { headers });
32799
33250
  }
32800
- file2 = Bun.file(join2(dashboardDist, "index.html"));
33251
+ file2 = Bun.file(join3(dashboardDist, "index.html"));
32801
33252
  if (await file2.exists()) {
32802
33253
  const headers = securityHeaders();
32803
33254
  if (file2.type)
@@ -32851,6 +33302,7 @@ init_sessions();
32851
33302
  init_spaces();
32852
33303
  init_projects();
32853
33304
  init_db();
33305
+ init_identity();
32854
33306
  init_presence();
32855
33307
  import chalk2 from "chalk";
32856
33308
  import { render } from "ink";
@@ -34598,17 +35050,18 @@ program2.command("unpin").description("Unpin a message").argument("<id>", "Messa
34598
35050
  }
34599
35051
  closeDb();
34600
35052
  });
34601
- program2.command("agents").description("List all agents with their presence status").option("--online", "Only show online agents").option("--json", "Output as JSON").action((opts) => {
35053
+ var agents = program2.command("agents").description("Manage agents");
35054
+ agents.command("list").description("List all agents with their presence status").option("--online", "Only show online agents").option("--json", "Output as JSON").action((opts) => {
34602
35055
  const agent = resolveIdentity();
34603
35056
  heartbeat(agent);
34604
- const agents = listAgents({ online_only: opts.online });
35057
+ const agentsList = listAgents({ online_only: opts.online });
34605
35058
  if (opts.json) {
34606
- console.log(JSON.stringify(agents, null, 2));
35059
+ console.log(JSON.stringify(agentsList, null, 2));
34607
35060
  } else {
34608
- if (agents.length === 0) {
35061
+ if (agentsList.length === 0) {
34609
35062
  console.log(chalk2.dim("No agents found."));
34610
35063
  } else {
34611
- for (const a of agents) {
35064
+ for (const a of agentsList) {
34612
35065
  const status = a.online ? chalk2.green("online") : chalk2.dim("offline");
34613
35066
  const lastSeen = chalk2.dim(a.last_seen_at.slice(0, 19));
34614
35067
  const agentName = a.agent === agent ? chalk2.cyan(`${a.agent} (you)`) : chalk2.cyan(a.agent);
@@ -34618,6 +35071,49 @@ program2.command("agents").description("List all agents with their presence stat
34618
35071
  }
34619
35072
  closeDb();
34620
35073
  });
35074
+ agents.command("remove").description("Remove an agent from the presence list").argument("<name>", "Agent name to remove").option("--json", "Output as JSON").action((name, opts) => {
35075
+ const agentName = typeof name === "string" ? name.trim() : "";
35076
+ if (!agentName) {
35077
+ console.error(chalk2.red("Agent name cannot be empty."));
35078
+ process.exit(1);
35079
+ }
35080
+ const removed = removePresence(agentName);
35081
+ if (opts.json) {
35082
+ console.log(JSON.stringify({ agent: agentName, removed }));
35083
+ } else {
35084
+ if (removed) {
35085
+ console.log(chalk2.green(`Agent "${agentName}" removed.`));
35086
+ } else {
35087
+ console.error(chalk2.red(`Agent "${agentName}" not found.`));
35088
+ process.exit(1);
35089
+ }
35090
+ }
35091
+ closeDb();
35092
+ });
35093
+ agents.command("rename").description("Rename an agent in the presence list").argument("<old-name>", "Current agent name").argument("<new-name>", "New agent name").option("--json", "Output as JSON").action((oldName, newName, opts) => {
35094
+ const old = typeof oldName === "string" ? oldName.trim() : "";
35095
+ const renamed = typeof newName === "string" ? newName.trim() : "";
35096
+ if (!old || !renamed) {
35097
+ console.error(chalk2.red("Both old and new names are required."));
35098
+ process.exit(1);
35099
+ }
35100
+ try {
35101
+ const ok = renameAgent(old, renamed);
35102
+ if (!ok) {
35103
+ console.error(chalk2.red(`Agent "${old}" not found.`));
35104
+ process.exit(1);
35105
+ }
35106
+ if (opts.json) {
35107
+ console.log(JSON.stringify({ old_name: old, new_name: renamed, renamed: true }));
35108
+ } else {
35109
+ console.log(chalk2.green(`Agent "${old}" renamed to "${renamed}".`));
35110
+ }
35111
+ } catch (e) {
35112
+ console.error(chalk2.red(e.message));
35113
+ process.exit(1);
35114
+ }
35115
+ closeDb();
35116
+ });
34621
35117
  program2.command("mcp").description("Start MCP server").action(async () => {
34622
35118
  const { startMcpServer: startMcpServer2 } = await Promise.resolve().then(() => (init_mcp2(), exports_mcp));
34623
35119
  await startMcpServer2();