agent-dir 1.0.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.
- package/dist/bin/agent-dir.js +17 -4
- package/dist/src/codegraph.d.ts +1 -0
- package/dist/src/codegraph.js +12 -0
- package/dist/src/logging.d.ts +1 -0
- package/dist/src/logging.js +101 -43
- package/dist/src/mcp.d.ts +2 -1
- package/dist/src/mcp.js +5 -5
- package/dist/src/server.d.ts +1 -1
- package/dist/src/server.js +10 -5
- package/dist/src/tunnel.js +5 -4
- package/dist/src/types.d.ts +1 -0
- package/docs/RELEASING.md +7 -16
- package/package.json +1 -1
package/dist/bin/agent-dir.js
CHANGED
|
@@ -5,6 +5,7 @@ import { createRequire } from "node:module";
|
|
|
5
5
|
import { resolve } from "node:path";
|
|
6
6
|
import { createInterface } from "node:readline/promises";
|
|
7
7
|
import { parseArgs } from "node:util";
|
|
8
|
+
import { CodeGraphIntegration } from "../src/codegraph.js";
|
|
8
9
|
import { configPath, loadConfig, mergeProfile, saveConfig } from "../src/config.js";
|
|
9
10
|
import { printBanner, printHelp, printRequestHeader } from "../src/logging.js";
|
|
10
11
|
import { startServer } from "../src/server.js";
|
|
@@ -445,6 +446,10 @@ if (allowedCommands)
|
|
|
445
446
|
if (commandConfig.blacklistedCommands?.length) {
|
|
446
447
|
bannerOptions.blacklistedCommands = commandConfig.blacklistedCommands;
|
|
447
448
|
}
|
|
449
|
+
const codeGraph = new CodeGraphIntegration(directory);
|
|
450
|
+
const codeGraphCapability = await codeGraph.prepare();
|
|
451
|
+
if (codeGraphCapability.tool)
|
|
452
|
+
bannerOptions.codeGraph = true;
|
|
448
453
|
printBanner(bannerOptions);
|
|
449
454
|
const telemetrySessionId = randomUUID();
|
|
450
455
|
const server = await startServer({
|
|
@@ -452,18 +457,26 @@ const server = await startServer({
|
|
|
452
457
|
port,
|
|
453
458
|
token,
|
|
454
459
|
commandConfig,
|
|
460
|
+
codeGraph,
|
|
455
461
|
telemetry: {
|
|
456
462
|
...(config.telemetry ?? { level: "none" }),
|
|
457
463
|
...(telemetryConfigId ? { configId: telemetryConfigId } : {}),
|
|
458
464
|
sessionId: telemetrySessionId,
|
|
459
465
|
persist: true,
|
|
460
466
|
},
|
|
467
|
+
}).catch(async (error) => {
|
|
468
|
+
await codeGraph.close();
|
|
469
|
+
throw error;
|
|
461
470
|
});
|
|
462
471
|
let tunnelResult;
|
|
463
|
-
console.log("
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
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`);
|
|
467
480
|
if (tunnel !== "none") {
|
|
468
481
|
try {
|
|
469
482
|
tunnelResult = await startTunnel({
|
package/dist/src/codegraph.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export declare class CodeGraphIntegration {
|
|
|
18
18
|
private readonly pending;
|
|
19
19
|
constructor(root: string);
|
|
20
20
|
capability(): Promise<CodeGraphCapability>;
|
|
21
|
+
prepare(): Promise<CodeGraphCapability>;
|
|
21
22
|
explore(query: string, maxFiles?: number): Promise<Record<string, unknown>>;
|
|
22
23
|
close(): Promise<void>;
|
|
23
24
|
private detect;
|
package/dist/src/codegraph.js
CHANGED
|
@@ -27,6 +27,18 @@ export class CodeGraphIntegration {
|
|
|
27
27
|
this.capabilityPromise = this.detect();
|
|
28
28
|
return this.capabilityPromise;
|
|
29
29
|
}
|
|
30
|
+
async prepare() {
|
|
31
|
+
const capability = await this.capability();
|
|
32
|
+
if (capability.status === "available") {
|
|
33
|
+
try {
|
|
34
|
+
await this.ensureStarted();
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// Keep Agent Dir startup available even if CodeGraph fails to start.
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return this.capability();
|
|
41
|
+
}
|
|
30
42
|
async explore(query, maxFiles) {
|
|
31
43
|
const capability = await this.capability();
|
|
32
44
|
if (capability.status === "not_installed")
|
package/dist/src/logging.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare function printBanner(options: {
|
|
|
11
11
|
npmScripts?: string[];
|
|
12
12
|
commands?: string[];
|
|
13
13
|
blacklistedCommands?: string[];
|
|
14
|
+
codeGraph?: boolean;
|
|
14
15
|
}): void;
|
|
15
16
|
export declare function printRequestLog(entry: RequestLog): void;
|
|
16
17
|
export declare function logRequest(entry: RequestLog): void;
|
package/dist/src/logging.js
CHANGED
|
@@ -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,54 +173,51 @@ export function printHelp() {
|
|
|
112
173
|
}
|
|
113
174
|
export function printBanner(options) {
|
|
114
175
|
writeLine("");
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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(`
|
|
183
|
+
writeLine(boxContent(`${color("DOMAIN", DIM)} ${color(`https://${options.subdomain}.wormhole.bar`, BRIGHT_GREEN)}`, BRIGHT_CYAN));
|
|
134
184
|
if (options.hostname)
|
|
135
|
-
writeLine(`
|
|
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("
|
|
138
|
-
writeLine(
|
|
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("
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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));
|
|
152
212
|
writeLine("");
|
|
153
213
|
if (options.npmScripts?.length) {
|
|
154
|
-
writeLine("
|
|
155
|
-
|
|
156
|
-
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);
|
|
157
216
|
writeLine("");
|
|
158
217
|
}
|
|
159
218
|
if (options.commands?.length) {
|
|
160
|
-
writeLine("
|
|
161
|
-
|
|
162
|
-
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);
|
|
163
221
|
writeLine("");
|
|
164
222
|
}
|
|
165
223
|
}
|
|
@@ -206,7 +264,7 @@ export function logRequest(entry) {
|
|
|
206
264
|
}
|
|
207
265
|
export function printRequestHeader() {
|
|
208
266
|
writeLine("");
|
|
209
|
-
writeLine("
|
|
210
|
-
writeLine("
|
|
211
|
-
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));
|
|
212
270
|
}
|
package/dist/src/mcp.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CodeGraphIntegration } from "./codegraph.js";
|
|
1
2
|
import { TelemetryRecorder } from "./telemetry/recorder.js";
|
|
2
3
|
import type { TelemetryConfig } from "./telemetry/types.js";
|
|
3
4
|
import type { CommandConfig } from "./types.js";
|
|
@@ -6,6 +7,6 @@ interface McpHandler {
|
|
|
6
7
|
closeSubscriptions: () => void;
|
|
7
8
|
telemetrySnapshot: () => ReturnType<TelemetryRecorder["snapshot"]>;
|
|
8
9
|
}
|
|
9
|
-
export declare function createMcpHandler(root: string, commandConfig?: CommandConfig, telemetry?: TelemetryConfig): McpHandler;
|
|
10
|
+
export declare function createMcpHandler(root: string, commandConfig?: CommandConfig, telemetry?: TelemetryConfig, codeGraphIntegration?: CodeGraphIntegration): McpHandler;
|
|
10
11
|
export declare function validateMcpParamHeaders(inputSchema: Record<string, unknown>, args: Record<string, unknown>, headers: Headers): string | undefined;
|
|
11
12
|
export {};
|
package/dist/src/mcp.js
CHANGED
|
@@ -162,8 +162,8 @@ function tool(name, description, properties, outputSchema, required = []) {
|
|
|
162
162
|
outputSchema,
|
|
163
163
|
};
|
|
164
164
|
}
|
|
165
|
-
export function createMcpHandler(root, commandConfig = {}, telemetry = { level: "none" }) {
|
|
166
|
-
const codeGraph = new CodeGraphIntegration(root);
|
|
165
|
+
export function createMcpHandler(root, commandConfig = {}, telemetry = { level: "none" }, codeGraphIntegration) {
|
|
166
|
+
const codeGraph = codeGraphIntegration ?? new CodeGraphIntegration(root);
|
|
167
167
|
const telemetryRecorder = new TelemetryRecorder({
|
|
168
168
|
level: telemetry.level,
|
|
169
169
|
persist: telemetry.persist ?? false,
|
|
@@ -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 -
|
|
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": {
|
package/dist/src/server.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { ServerOptions } from "./types.js";
|
|
|
2
2
|
export interface ServerHandle {
|
|
3
3
|
close: () => Promise<void>;
|
|
4
4
|
}
|
|
5
|
-
export declare function startServer({ root, port, token, commandConfig, telemetry, }: ServerOptions): Promise<ServerHandle>;
|
|
5
|
+
export declare function startServer({ root, port, token, commandConfig, telemetry, codeGraph, }: ServerOptions): Promise<ServerHandle>;
|
|
6
6
|
export declare function validateMcpHeaders(request: Request, message: Record<string, unknown> | null): Response | undefined;
|
|
7
7
|
export declare function getMcpLog(body: Buffer, responseBody?: unknown): {
|
|
8
8
|
name: string;
|
package/dist/src/server.js
CHANGED
|
@@ -9,8 +9,8 @@ const REQUEST_TIMEOUT_MS = 120_000;
|
|
|
9
9
|
const HEADERS_TIMEOUT_MS = 30_000;
|
|
10
10
|
const KEEP_ALIVE_TIMEOUT_MS = 5_000;
|
|
11
11
|
const HEALTH_PATH = "/__health";
|
|
12
|
-
export function startServer({ root, port, token, commandConfig = {}, telemetry = { level: "none" }, }) {
|
|
13
|
-
const mcp = createMcpHandler(root, commandConfig, telemetry);
|
|
12
|
+
export function startServer({ root, port, token, commandConfig = {}, telemetry = { level: "none" }, codeGraph, }) {
|
|
13
|
+
const mcp = createMcpHandler(root, commandConfig, telemetry, codeGraph);
|
|
14
14
|
const httpTelemetry = new TelemetryRecorder({
|
|
15
15
|
level: telemetry.level,
|
|
16
16
|
persist: telemetry.persist ?? false,
|
|
@@ -138,10 +138,15 @@ export function startServer({ root, port, token, commandConfig = {}, telemetry =
|
|
|
138
138
|
return new Promise((resolve, reject) => {
|
|
139
139
|
server.once("error", reject);
|
|
140
140
|
server.listen(port, "127.0.0.1", () => resolve({
|
|
141
|
-
close:
|
|
141
|
+
close: async () => {
|
|
142
142
|
mcp.closeSubscriptions();
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
try {
|
|
144
|
+
await new Promise((done) => server.close(() => done()));
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
await codeGraph?.close();
|
|
148
|
+
}
|
|
149
|
+
},
|
|
145
150
|
}));
|
|
146
151
|
});
|
|
147
152
|
}
|
package/dist/src/tunnel.js
CHANGED
|
@@ -95,10 +95,11 @@ export function startTunnel(options) {
|
|
|
95
95
|
record(event);
|
|
96
96
|
if (event.type === "online") {
|
|
97
97
|
writeLine();
|
|
98
|
-
writeLine(
|
|
99
|
-
writeLine(`
|
|
100
|
-
writeLine(`
|
|
101
|
-
writeLine(`
|
|
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/dist/src/types.d.ts
CHANGED
package/docs/RELEASING.md
CHANGED
|
@@ -6,10 +6,7 @@ This document is the authoritative maintainer/agent procedure for publishing `ag
|
|
|
6
6
|
|
|
7
7
|
feature/*
|
|
8
8
|
│
|
|
9
|
-
|
|
10
|
-
│ └── CI
|
|
11
|
-
│
|
|
12
|
-
└── promotion PR → main
|
|
9
|
+
└── PR → main
|
|
13
10
|
└── CI
|
|
14
11
|
│
|
|
15
12
|
▼
|
|
@@ -28,7 +25,7 @@ This document is the authoritative maintainer/agent procedure for publishing `ag
|
|
|
28
25
|
├── create GitHub Release
|
|
29
26
|
└── publish npm package
|
|
30
27
|
|
|
31
|
-
`main`
|
|
28
|
+
`main` is the single protected release branch. Normal human and agent changes reach it through pull requests. There is no permanent `staging` branch.
|
|
32
29
|
|
|
33
30
|
## Release source of truth
|
|
34
31
|
|
|
@@ -61,21 +58,15 @@ Do not manually edit the package version.
|
|
|
61
58
|
|
|
62
59
|
`npm pack --dry-run` is important: inspect the file list and make sure the package does not contain credentials, local configuration, development-only files, or other unintended content.
|
|
63
60
|
|
|
64
|
-
### 3.
|
|
61
|
+
### 3. Open and merge a pull request
|
|
65
62
|
|
|
66
|
-
Push the
|
|
63
|
+
Push the branch and open a PR targeting `main`.
|
|
67
64
|
|
|
68
65
|
The required CI check is `Check`. It runs `npm ci`, `npm run check`, `npm test`, and `npm pack --dry-run`.
|
|
69
66
|
|
|
70
|
-
Do not bypass a failing check.
|
|
71
|
-
|
|
72
|
-
### 4. Promote staging to main
|
|
73
|
-
|
|
74
|
-
Create a promotion PR: `staging → main`.
|
|
75
|
-
|
|
76
|
-
CI runs again because `main` is also a pull-request target. Merge only after the required `Check` status is green.
|
|
67
|
+
Do not bypass a failing check. Merge only after the required `Check` status is green and the required review is approved.
|
|
77
68
|
|
|
78
|
-
###
|
|
69
|
+
### 4. Let GitHub Actions publish
|
|
79
70
|
|
|
80
71
|
The merge to `main` creates a push to `main`, which starts `.github/workflows/publish.yml`.
|
|
81
72
|
|
|
@@ -179,7 +170,7 @@ If a release was partially created, reconcile the actual Git/npm/GitHub state be
|
|
|
179
170
|
|
|
180
171
|
## CI workflow constraints
|
|
181
172
|
|
|
182
|
-
`.github/workflows/ci.yml` runs
|
|
173
|
+
`.github/workflows/ci.yml` runs on pushes to `main` and pull requests targeting `main`.
|
|
183
174
|
|
|
184
175
|
Its concurrency key must remain safe for both PR events and any diagnostic/manual event that may temporarily be introduced:
|
|
185
176
|
|
package/package.json
CHANGED