agent-coord-mcp 0.3.8 → 0.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-coord-mcp",
3
- "version": "0.3.8",
3
+ "version": "0.3.10",
4
4
  "description": "File-backed MCP server for coordinating multiple AI coding agents (Claude Code, Cursor, Cline, etc.) on the same machine.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -108,19 +108,33 @@ const SLASH_COMMANDS = [
108
108
  ];
109
109
 
110
110
  function completer(line) {
111
- // Tab-complete slash commands and DM targets.
111
+ // Tab-complete slash commands and DM targets. On multi-match with no
112
+ // common-prefix advancement, surface the options on the first Tab via
113
+ // say() — default readline UX hides them until a second Tab, which most
114
+ // users assume means "nothing happened."
115
+ let hits = [];
112
116
  if (line.startsWith("/dm ")) {
113
117
  const partial = line.slice(4);
114
118
  const reg = readJsonSafe(AGENTS_FILE, {});
115
119
  const ids = Object.keys(reg).filter((id) => id !== ID && id.startsWith(partial));
116
- const hits = ids.map((id) => `/dm ${id} `);
117
- return [hits, line];
120
+ hits = ids.map((id) => `/dm ${id} `);
121
+ } else if (line.startsWith("/")) {
122
+ hits = SLASH_COMMANDS.filter((c) => c.startsWith(line));
118
123
  }
119
- if (line.startsWith("/")) {
120
- const hits = SLASH_COMMANDS.filter((c) => c.startsWith(line));
121
- return [hits, line];
124
+ if (hits.length > 1 && commonPrefix(hits).length <= line.length) {
125
+ const display = hits.map((h) => h.trim()).join(" ");
126
+ say(A.dim(" ┄ " + display));
122
127
  }
123
- return [[], line];
128
+ return [hits, line];
129
+ }
130
+
131
+ function commonPrefix(strs) {
132
+ if (strs.length === 0) return "";
133
+ let p = strs[0];
134
+ for (const s of strs.slice(1)) {
135
+ while (s.indexOf(p) !== 0) p = p.slice(0, -1);
136
+ }
137
+ return p;
124
138
  }
125
139
 
126
140
  const rl = readline.createInterface({
@@ -164,6 +178,8 @@ rl.on("line", async (line) => {
164
178
  await printWhoami();
165
179
  } else if (text === "/clear" || text === "/cls") {
166
180
  process.stdout.write("\x1b[2J\x1b[H");
181
+ // No sep above the prompt yet — the post-Enter path will write one.
182
+ inputAreaReady = false;
167
183
  printBanner();
168
184
  } else if (text.startsWith("/last")) {
169
185
  const m = text.match(/^\/last(?:\s+(\d+))?$/);
@@ -188,6 +204,7 @@ rl.on("line", async (line) => {
188
204
  // After Enter, terminal advanced to a new line. Print a fresh separator
189
205
  // there so the next prompt sits below a sep line, maintaining the layout.
190
206
  process.stdout.write(sepLine() + "\n");
207
+ inputAreaReady = true;
191
208
  rl.prompt();
192
209
  });
193
210
 
@@ -264,15 +281,14 @@ function refreshPrompt() {
264
281
  }
265
282
 
266
283
  function printBanner() {
267
- // Compact bannerthree lines plus a separator. ASCII so it renders
268
- // anywhere; no UTF-8 box-drawing surprises.
284
+ // Banner lines are static no need to go through say() and its
285
+ // sep-overwrite logic, which corrupts layout when called after /clear.
269
286
  const lines = [
270
287
  A.bold(A.cyan(" agent-coord ")) + A.dim("— shared chat for agents and humans"),
271
288
  A.dim(` agentId=${A.reset}${agentColor(ID)(ID)}${A.dim(" dir=" + ROOT)}`),
272
289
  A.dim(" type /help for commands · /quit to leave"),
273
290
  ];
274
- for (const l of lines) say(l);
275
- say(A.dim(" " + "─".repeat(60)));
291
+ for (const l of lines) process.stdout.write(l + "\n");
276
292
  }
277
293
 
278
294
  function printHelp() {