agent-dir 1.1.0 → 1.1.1

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.
@@ -469,10 +469,14 @@ const server = await startServer({
469
469
  throw error;
470
470
  });
471
471
  let tunnelResult;
472
- console.log(" ✓ SERVER ONLINE");
473
- console.log(` Local target : http://127.0.0.1:${port}`);
474
- console.log(" Auth : Bearer token");
475
- console.log(" Token : <configured>");
472
+ console.log(` ${"╭─ SERVER ONLINE ".padEnd(76, "─")}╮`
473
+ .replace("╭", "\x1b[92m╭")
474
+ .replace(/─/g, "─\x1b[92m")
475
+ .replace("╮", "╮\x1b[0m"));
476
+ console.log(` \x1b[92m│\x1b[0m ${"Local target".padEnd(14)}: http://127.0.0.1:${port}`);
477
+ console.log(` \x1b[92m│\x1b[0m ${"Auth".padEnd(14)}: Bearer token`);
478
+ console.log(` \x1b[92m│\x1b[0m ${"Token".padEnd(14)}: <configured>`);
479
+ console.log(` \x1b[92m╰${"─".repeat(74)}╯\x1b[0m`);
476
480
  if (tunnel !== "none") {
477
481
  try {
478
482
  tunnelResult = await startTunnel({
@@ -4,11 +4,11 @@ const MAGENTA = "\x1b[35m";
4
4
  const YELLOW = "\x1b[33m";
5
5
  const RED = "\x1b[31m";
6
6
  const GREEN = "\x1b[32m";
7
- const BLUE = "\x1b[34m";
8
7
  const BRIGHT_BLUE = "\x1b[94m";
9
8
  const BRIGHT_CYAN = "\x1b[96m";
10
9
  const BRIGHT_MAGENTA = "\x1b[95m";
11
10
  const BRIGHT_YELLOW = "\x1b[93m";
11
+ const BRIGHT_GREEN = "\x1b[92m";
12
12
  const writeLine = (line = "") => {
13
13
  process.stdout.write(`${line}\r\n`);
14
14
  };
@@ -56,6 +56,67 @@ const TOOL_COLORS = {
56
56
  };
57
57
  const NARROW_TOOL_ICONS = new Set(["✎", "✖", "⚙", "⌘", "↪", "↗"]);
58
58
  const TOOL_ICON_SLOT_WIDTH = 3;
59
+ const DIM = "\x1b[90m";
60
+ function visibleLength(value) {
61
+ const esc = String.fromCharCode(27);
62
+ const plain = value
63
+ .replaceAll(`${esc}[90m`, "")
64
+ .replaceAll(`${esc}[0m`, "")
65
+ .replaceAll(`${esc}[92m`, "")
66
+ .replaceAll(`${esc}[96m`, "")
67
+ .replaceAll(`${esc}[95m`, "")
68
+ .replaceAll(`${esc}[94m`, "")
69
+ .replaceAll(`${esc}[93m`, "")
70
+ .replaceAll(`${esc}[32m`, "")
71
+ .replaceAll(`${esc}[36m`, "")
72
+ .replaceAll(`${esc}[35m`, "")
73
+ .replaceAll(`${esc}[34m`, "")
74
+ .replaceAll(`${esc}[33m`, "");
75
+ let width = 0;
76
+ for (const character of plain) {
77
+ const code = character.codePointAt(0) ?? 0;
78
+ width +=
79
+ code >= 0x1100 &&
80
+ (code <= 0x115f ||
81
+ code === 0x2329 ||
82
+ code === 0x232a ||
83
+ (code >= 0x2e80 && code <= 0xa4cf) ||
84
+ (code >= 0xac00 && code <= 0xd7a3) ||
85
+ (code >= 0xf900 && code <= 0xfaff) ||
86
+ (code >= 0xfe10 && code <= 0xfe19) ||
87
+ (code >= 0xfe30 && code <= 0xfe6f) ||
88
+ (code >= 0xff00 && code <= 0xff60) ||
89
+ (code >= 0xffe0 && code <= 0xffe6) ||
90
+ (code >= 0x1f300 && code <= 0x1faff))
91
+ ? 2
92
+ : 1;
93
+ }
94
+ return width;
95
+ }
96
+ const BOX_WIDTH = 76;
97
+ function boxTop(label, borderColor, width = BOX_WIDTH) {
98
+ const heading = `─ ${label} `;
99
+ return ` ${color(`╭${heading}${"─".repeat(Math.max(1, width - visibleLength(heading) - 2))}╮`, borderColor)}`;
100
+ }
101
+ function boxContent(content, borderColor, width = BOX_WIDTH) {
102
+ const padding = Math.max(0, width - visibleLength(content) - 3);
103
+ return ` ${color("│", borderColor)} ${content}${" ".repeat(padding)}${color("│", borderColor)}`;
104
+ }
105
+ function boxBottom(borderColor, width = BOX_WIDTH) {
106
+ return ` ${color(`╰${"─".repeat(width - 2)}╯`, borderColor)}`;
107
+ }
108
+ function printGrid(items, columns = 2) {
109
+ const width = Math.max(40, Math.min(100, (process.stdout.columns || 100) - 4));
110
+ const columnWidth = Math.floor(width / columns);
111
+ for (let index = 0; index < items.length; index += columns) {
112
+ const row = items.slice(index, index + columns);
113
+ writeLine(` ${row
114
+ .map((item) => item +
115
+ " ".repeat(Math.max(1, columnWidth -
116
+ item.replace(new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g"), "").length)))
117
+ .join("")}`);
118
+ }
119
+ }
59
120
  function toolIcon(name) {
60
121
  return TOOL_ICONS[name] ?? MCP_METHOD_ICONS[name] ?? "•";
61
122
  }
@@ -112,57 +173,51 @@ export function printHelp() {
112
173
  }
113
174
  export function printBanner(options) {
114
175
  writeLine("");
115
- const banner = [
116
- "╭──────────────────────────────────────────────────────────────╮",
117
- "│ AGENT-DIR │",
118
- "╰──────────────────────────────────────────────────────────────╯",
119
- ];
120
- const gradient = [BRIGHT_CYAN, BRIGHT_BLUE, BRIGHT_MAGENTA];
121
- for (let i = 0; i < banner.length; i++) {
122
- writeLine(color(banner[i] ?? "", gradient[i] ?? BRIGHT_CYAN));
123
- }
124
- writeLine("");
125
- writeLine(` Directory ${options.root}`);
126
- writeLine(` Port ${options.port}`);
127
- writeLine(` Config ${options.profileName ?? "CLI options"}`);
128
- writeLine(` Tunnel ${options.tunnel}`);
129
- if (options.blacklistedCommands?.length) {
130
- writeLine(` Blocked ${options.blacklistedCommands.join(", ")}`);
131
- }
176
+ writeLine(color(" ╭──────────────────────────────────────────────────────────────────────────────╮", BRIGHT_CYAN));
177
+ writeLine(`${color(" │", BRIGHT_CYAN)} ${color("AGENT", BRIGHT_CYAN)}${color("·", BRIGHT_MAGENTA)}${color("DIR", BRIGHT_BLUE)} ${color("LOCAL PROJECT BRIDGE", BRIGHT_MAGENTA)}`);
178
+ writeLine(color(" ╰──────────────────────────────────────────────────────────────────────────────╯", BRIGHT_CYAN));
179
+ writeLine(` ${color("● SESSION", BRIGHT_GREEN)} ${color(options.profileName ?? "CLI options", BRIGHT_CYAN)} ${color("│", DIM)} ${color(options.tunnel.toUpperCase(), BRIGHT_MAGENTA)} ${color("│", DIM)} ${color(`PORT ${options.port}`, BRIGHT_BLUE)}`);
180
+ writeLine(boxTop("PROJECT", BRIGHT_CYAN));
181
+ writeLine(boxContent(`${color("DIR", DIM)} ${options.root}`, BRIGHT_CYAN));
132
182
  if (options.subdomain)
133
- writeLine(` Domain https://${options.subdomain}.wormhole.bar`);
183
+ writeLine(boxContent(`${color("DOMAIN", DIM)} ${color(`https://${options.subdomain}.wormhole.bar`, BRIGHT_GREEN)}`, BRIGHT_CYAN));
134
184
  if (options.hostname)
135
- writeLine(` Domain https://${options.hostname}`);
185
+ writeLine(boxContent(`${color("DOMAIN", DIM)} ${color(`https://${options.hostname}`, BRIGHT_GREEN)}`, BRIGHT_CYAN));
186
+ if (options.blacklistedCommands?.length)
187
+ writeLine(boxContent(`${color("BLOCKED", BRIGHT_YELLOW)} ${options.blacklistedCommands.join(", ")}`, BRIGHT_CYAN));
188
+ writeLine(boxBottom(BRIGHT_CYAN));
136
189
  writeLine("");
137
- writeLine(" MCP");
138
- writeLine(` ${color("⚡ /mcp", CYAN)}`);
190
+ writeLine(boxTop("MCP ENDPOINT", BRIGHT_MAGENTA));
191
+ writeLine(boxContent(`${color("⚡ POST", BRIGHT_YELLOW)} ${color("/mcp", BRIGHT_CYAN)} ${color("JSON-RPC · tools · resources", DIM)}`, BRIGHT_MAGENTA));
192
+ writeLine(boxBottom(BRIGHT_MAGENTA));
139
193
  writeLine("");
140
- writeLine(" TOOLS");
141
- writeLine(` ${color(toolLabel("project_context"), BRIGHT_CYAN)}`);
142
- writeLine(` ${color(toolLabel("find_files"), CYAN)}`);
143
- writeLine(` ${color(toolLabel("search_code"), BRIGHT_CYAN)}`);
144
- writeLine(` ${color(toolLabel("find_symbol"), GREEN)}`);
145
- writeLine(` ${color(toolLabel("find_references"), GREEN)}`);
146
- writeLine(` ${color(toolLabel("read_range"), GREEN)}`);
147
- writeLine(` ${color(toolLabel("apply_changes"), BRIGHT_MAGENTA)}`);
148
- writeLine(` ${color(toolLabel("validate"), BRIGHT_YELLOW)}`);
149
- writeLine(` ${color(toolLabel("run_npm_batch"), BRIGHT_BLUE)}`);
150
- writeLine(` ${color(toolLabel("run_command_batch"), BRIGHT_CYAN)}`);
151
- writeLine(` ${color(toolLabel("file_info"), YELLOW)}`);
152
- if (options.codeGraph) {
153
- writeLine(` ${color(toolLabel("codegraph_explore"), BRIGHT_MAGENTA)}`);
154
- }
194
+ writeLine(boxTop("AVAILABLE TOOLS", BRIGHT_BLUE));
195
+ const toolRows = [
196
+ color(toolLabel("project_context"), BRIGHT_CYAN),
197
+ color(toolLabel("find_files"), CYAN),
198
+ color(toolLabel("search_code"), BRIGHT_CYAN),
199
+ color(toolLabel("find_symbol"), GREEN),
200
+ color(toolLabel("find_references"), GREEN),
201
+ color(toolLabel("read_range"), GREEN),
202
+ color(toolLabel("apply_changes"), BRIGHT_MAGENTA),
203
+ color(toolLabel("validate"), BRIGHT_YELLOW),
204
+ color(toolLabel("run_npm_batch"), BRIGHT_BLUE),
205
+ color(toolLabel("run_command_batch"), BRIGHT_CYAN),
206
+ color(toolLabel("file_info"), YELLOW),
207
+ ];
208
+ if (options.codeGraph)
209
+ toolRows.push(color(toolLabel("codegraph_explore"), BRIGHT_MAGENTA));
210
+ printGrid(toolRows, 2);
211
+ writeLine(boxBottom(BRIGHT_BLUE));
155
212
  writeLine("");
156
213
  if (options.npmScripts?.length) {
157
- writeLine(" NPM COMMANDS");
158
- for (const script of options.npmScripts)
159
- writeLine(` ${color("•", BLUE)} npm run ${script}`);
214
+ writeLine(` ${color("◆ NPM SCRIPTS", BRIGHT_YELLOW)} ${color("· scripts are allowlisted", "\x1b[90m")}`);
215
+ printGrid(options.npmScripts.map((script) => `${color("›", BRIGHT_YELLOW)} ${color("npm run", BRIGHT_YELLOW)} ${color(script, BRIGHT_CYAN)}`), 2);
160
216
  writeLine("");
161
217
  }
162
218
  if (options.commands?.length) {
163
- writeLine(" ALLOWED COMMANDS");
164
- for (const command of options.commands)
165
- writeLine(` ${color("•", CYAN)} ${command}`);
219
+ writeLine(` ${color("◆ COMMAND ALLOWLIST", BRIGHT_GREEN)} ${color("· shell access is restricted", "\x1b[90m")}`);
220
+ printGrid(options.commands.map((command) => `${color("›", BRIGHT_GREEN)} ${color(command, CYAN)}`), 3);
166
221
  writeLine("");
167
222
  }
168
223
  }
@@ -209,7 +264,7 @@ export function logRequest(entry) {
209
264
  }
210
265
  export function printRequestHeader() {
211
266
  writeLine("");
212
- writeLine(" ──────────────────────────────────────────────────────────────");
213
- writeLine(" [Request logs]");
214
- writeLine(" ──────────────────────────────────────────────────────────────");
267
+ writeLine(boxTop("REQUEST STREAM", BRIGHT_MAGENTA));
268
+ writeLine(boxContent(color("Live MCP traffic · method · status · tool activity", DIM), BRIGHT_MAGENTA));
269
+ writeLine(boxBottom(BRIGHT_MAGENTA));
215
270
  }
package/dist/src/mcp.js CHANGED
@@ -774,12 +774,12 @@ async function callTool(name, args, root, npmAllowed, allowedCommands, blacklist
774
774
  const serialized = JSON.stringify(result);
775
775
  if (Buffer.byteLength(serialized, "utf8") <= maxBytes)
776
776
  return result;
777
- return {
777
+ return completeToolResult({
778
778
  truncated: true,
779
779
  originalBytes: Buffer.byteLength(serialized, "utf8"),
780
780
  message: "CodeGraph response exceeded the output budget. Narrow the query or lower maxFiles.",
781
- preview: truncateText(serialized, Math.min(2_000, maxBytes - 256)).text,
782
- };
781
+ preview: truncateText(serialized, Math.min(2_000, Math.max(256, maxBytes - 512))).text,
782
+ });
783
783
  }
784
784
  switch (name) {
785
785
  case "read_range": {
@@ -95,10 +95,11 @@ export function startTunnel(options) {
95
95
  record(event);
96
96
  if (event.type === "online") {
97
97
  writeLine();
98
- writeLine(" ✓ TUNNEL ONLINE");
99
- writeLine(` Public URL : ${event.url}`);
100
- writeLine(` MCP endpoint : ${event.url}/mcp`);
101
- writeLine(` Forwarding : ${event.url} → http://127.0.0.1:${options.port}`);
98
+ writeLine(` \x1b[96m╭─ TUNNEL ONLINE ${"─".repeat(58)}╮\x1b[0m`);
99
+ writeLine(` \x1b[96m│\x1b[0m Public URL : \x1b[92m${event.url}\x1b[0m`);
100
+ writeLine(` \x1b[96m│\x1b[0m MCP endpoint : \x1b[96m${event.url}/mcp\x1b[0m`);
101
+ writeLine(` \x1b[96m│\x1b[0m Forwarding : ${event.url} → http://127.0.0.1:${options.port}`);
102
+ writeLine(` \x1b[96m╰${"─".repeat(74)}╯\x1b[0m`);
102
103
  writeLine();
103
104
  }
104
105
  else if (event.type === "disconnected") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-dir",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Expose a local project to an AI agent through authenticated MCP, filesystem tools, and allowlisted development commands",
5
5
  "repository": {
6
6
  "type": "git",