@stage-labs/metro 0.1.0-beta.43 → 0.1.0-beta.45
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": "@stage-labs/metro",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.45",
|
|
4
4
|
"description": "The metro command line. Sign in once per machine, then hand your MCP connector list to Claude Code without the credentials touching disk, argv or shell history.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -4,6 +4,7 @@ import { apiFailure, apiSession, cors, sendJson } from './api-http.js';
|
|
|
4
4
|
import { ApiError } from './api-error.js';
|
|
5
5
|
import {
|
|
6
6
|
claudeDir,
|
|
7
|
+
deleteClaudeSession,
|
|
7
8
|
listClaudeProjects,
|
|
8
9
|
listClaudeSessions,
|
|
9
10
|
listMemory,
|
|
@@ -48,9 +49,14 @@ const ITEMS: Record<string, Handler> = {
|
|
|
48
49
|
memory: (query, dir, name) => ({ name, content: readMemoryFile(projectOf(query), name, dir) }),
|
|
49
50
|
};
|
|
50
51
|
|
|
51
|
-
function answer(path: string, query: URLSearchParams, dir: string): unknown {
|
|
52
|
+
function answer(method: string, path: string, query: URLSearchParams, dir: string): unknown {
|
|
52
53
|
const rest = path.slice(PREFIX.length + 1).split('/').filter(Boolean);
|
|
53
54
|
const [head = '', item] = rest;
|
|
55
|
+
if (method === 'DELETE') {
|
|
56
|
+
if (rest.length !== 2 || head !== 'sessions') throw new ApiError('method not allowed', 405);
|
|
57
|
+
deleteClaudeSession(projectOf(query), item ?? '', dir);
|
|
58
|
+
return { deleted: item };
|
|
59
|
+
}
|
|
54
60
|
const handler = rest.length === 1 ? COLLECTIONS[head] : rest.length === 2 ? ITEMS[head] : undefined;
|
|
55
61
|
if (handler === undefined) throw new ApiError('no such route', 404);
|
|
56
62
|
return handler(query, dir, item ?? '');
|
|
@@ -67,7 +73,7 @@ export function handleClaudeRequest(
|
|
|
67
73
|
res.writeHead(204, cors(req)).end();
|
|
68
74
|
return true;
|
|
69
75
|
}
|
|
70
|
-
if (req.method !== 'GET') {
|
|
76
|
+
if (req.method !== 'GET' && req.method !== 'DELETE') {
|
|
71
77
|
sendJson(req, res, 405, { error: 'method not allowed' });
|
|
72
78
|
return true;
|
|
73
79
|
}
|
|
@@ -79,7 +85,7 @@ export function handleClaudeRequest(
|
|
|
79
85
|
Promise.resolve()
|
|
80
86
|
.then(() => {
|
|
81
87
|
deps.authorize(session.subject);
|
|
82
|
-
return answer(path, new URLSearchParams(search), (deps.dir ?? claudeDir)());
|
|
88
|
+
return answer(req.method ?? 'GET', path, new URLSearchParams(search), (deps.dir ?? claudeDir)());
|
|
83
89
|
})
|
|
84
90
|
.then((body) => {
|
|
85
91
|
sendJson(req, res, 200, body);
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
openSync,
|
|
6
6
|
readdirSync,
|
|
7
7
|
readSync,
|
|
8
|
+
rmSync,
|
|
8
9
|
statSync,
|
|
9
10
|
} from 'node:fs';
|
|
10
11
|
import { homedir } from 'node:os';
|
|
@@ -273,6 +274,15 @@ export async function readTranscript(
|
|
|
273
274
|
return { entries, total, next: offset + limit < total ? offset + limit : null };
|
|
274
275
|
}
|
|
275
276
|
|
|
277
|
+
export function deleteClaudeSession(project: string, session: string, dir = claudeDir()): void {
|
|
278
|
+
const root = projectDir(project, dir);
|
|
279
|
+
const id = safeName(session, SESSION_RE, 'session id');
|
|
280
|
+
const file = join(root, `${id}.jsonl`);
|
|
281
|
+
if (!existsSync(file)) throw new ApiError('no such session', 404);
|
|
282
|
+
rmSync(file);
|
|
283
|
+
rmSync(join(root, id), { recursive: true, force: true });
|
|
284
|
+
}
|
|
285
|
+
|
|
276
286
|
export interface MemoryFile {
|
|
277
287
|
name: string;
|
|
278
288
|
bytes: number;
|
|
@@ -2,8 +2,13 @@ import { hostname } from 'node:os';
|
|
|
2
2
|
|
|
3
3
|
const uiBase = (): string => process.env.METRO_UI_URL ?? 'https://metro.box';
|
|
4
4
|
|
|
5
|
-
export const connectLink = (base: string): string =>
|
|
6
|
-
|
|
5
|
+
export const connectLink = (base: string): string => {
|
|
6
|
+
try {
|
|
7
|
+
return `${uiBase()}/#/${new URL(base).host}`;
|
|
8
|
+
} catch {
|
|
9
|
+
return `${uiBase()}/#/connect/${encodeURIComponent(base)}`;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
7
12
|
|
|
8
13
|
export function localConnectHint(port: number): string {
|
|
9
14
|
const here = `http://127.0.0.1:${String(port)}`;
|
package/runtime/runtime.json
CHANGED