frely-cli 0.6.2 → 0.6.6
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/README.md +117 -50
- package/dist/agent-help.d.ts +47 -58
- package/dist/agent-help.js +24 -10
- package/dist/agent-help.js.map +1 -1
- package/dist/cloud.d.ts +7 -0
- package/dist/cloud.js +263 -0
- package/dist/cloud.js.map +1 -0
- package/dist/device/connection-status.d.ts +42 -0
- package/dist/device/connection-status.js +112 -0
- package/dist/device/connection-status.js.map +1 -0
- package/dist/device/relay-client.d.ts +5 -1
- package/dist/device/relay-client.js +101 -43
- package/dist/device/relay-client.js.map +1 -1
- package/dist/diagnostics.d.ts +66 -4
- package/dist/diagnostics.js +133 -25
- package/dist/diagnostics.js.map +1 -1
- package/dist/index.js +35 -16
- package/dist/index.js.map +1 -1
- package/dist/mcp-authorization.js +3 -3
- package/dist/mcp-authorization.js.map +1 -1
- package/dist/mcp-command.d.ts +9 -0
- package/dist/mcp-command.js +68 -0
- package/dist/mcp-command.js.map +1 -0
- package/dist/runtime/mcp.d.ts +2 -0
- package/dist/runtime/mcp.js +8 -3
- package/dist/runtime/mcp.js.map +1 -1
- package/dist/service.d.ts +4 -0
- package/dist/service.js +28 -4
- package/dist/service.js.map +1 -1
- package/dist/upgrade/installation.d.ts +24 -0
- package/dist/upgrade/installation.js +137 -0
- package/dist/upgrade/installation.js.map +1 -0
- package/dist/upgrade/maintenance.d.ts +15 -0
- package/dist/upgrade/maintenance.js +133 -0
- package/dist/upgrade/maintenance.js.map +1 -0
- package/dist/upgrade/release.d.ts +9 -0
- package/dist/upgrade/release.js +45 -0
- package/dist/upgrade/release.js.map +1 -0
- package/dist/upgrade/service-refresh.d.ts +38 -0
- package/dist/upgrade/service-refresh.js +138 -0
- package/dist/upgrade/service-refresh.js.map +1 -0
- package/dist/upgrade/update.d.ts +49 -0
- package/dist/upgrade/update.js +228 -0
- package/dist/upgrade/update.js.map +1 -0
- package/package.json +1 -1
package/dist/cloud.js
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { createServer } from "node:http";
|
|
3
|
+
import { readFile, stat } from "node:fs/promises";
|
|
4
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
5
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
6
|
+
import { UnauthorizedError } from "@modelcontextprotocol/sdk/client/auth.js";
|
|
7
|
+
import { credentialStore } from "./credential-store.js";
|
|
8
|
+
import { inspectAuth, normalizeRelayUrl, openVerificationUrl } from "./auth.js";
|
|
9
|
+
import { VERSION } from "./version.js";
|
|
10
|
+
const SERVICE = "frely-cli-cloud-v1";
|
|
11
|
+
const SCOPE = "openid profile offline_access cloud:read cloud:write cloud:execute cloud:publish";
|
|
12
|
+
export const CLOUD_USAGE = `Frely Cloud — call your Frely application.
|
|
13
|
+
frely cloud list [--group <name>]
|
|
14
|
+
frely cloud describe <tool>
|
|
15
|
+
frely cloud call <tool> [--json '<object>' | --input <file>]
|
|
16
|
+
frely cloud login
|
|
17
|
+
frely cloud logout
|
|
18
|
+
|
|
19
|
+
Results are JSON. Cloud authorization is separate from device MCP.
|
|
20
|
+
Calls may create resources or incur usage. Failed writes are never replayed automatically.
|
|
21
|
+
`;
|
|
22
|
+
async function cloudIdentity() {
|
|
23
|
+
const account = await inspectAuth();
|
|
24
|
+
const origin = normalizeRelayUrl(account.relayUrl);
|
|
25
|
+
const resource = origin + "/mcp";
|
|
26
|
+
return { origin, resource, userId: account.user?.id, key: resource + "|" + (account.user?.id ?? "cloud") };
|
|
27
|
+
}
|
|
28
|
+
export async function logoutCloud() {
|
|
29
|
+
const identity = await cloudIdentity();
|
|
30
|
+
const raw = await credentialStore.getPassword(SERVICE, identity.key);
|
|
31
|
+
if (!raw)
|
|
32
|
+
return;
|
|
33
|
+
const stored = JSON.parse(raw);
|
|
34
|
+
if (stored.resource !== identity.resource)
|
|
35
|
+
throw new Error("Cloud credential resource mismatch.");
|
|
36
|
+
if (stored.tokens && stored.client) {
|
|
37
|
+
const token = stored.tokens.refresh_token ?? stored.tokens.access_token;
|
|
38
|
+
const response = await fetch(identity.origin + "/api/auth/oauth2/revoke", {
|
|
39
|
+
method: "POST", redirect: "error", signal: AbortSignal.timeout(15000),
|
|
40
|
+
headers: { "content-type": "application/x-www-form-urlencoded", origin: identity.origin },
|
|
41
|
+
body: new URLSearchParams({ client_id: stored.client.client_id, token,
|
|
42
|
+
token_type_hint: stored.tokens.refresh_token ? "refresh_token" : "access_token" }),
|
|
43
|
+
});
|
|
44
|
+
if (!response.ok)
|
|
45
|
+
throw new Error("Cloud authorization revocation failed. Try again.");
|
|
46
|
+
}
|
|
47
|
+
await credentialStore.deletePassword(SERVICE, identity.key);
|
|
48
|
+
}
|
|
49
|
+
async function connectCloud() {
|
|
50
|
+
const identity = await cloudIdentity();
|
|
51
|
+
const raw = await credentialStore.getPassword(SERVICE, identity.key);
|
|
52
|
+
let stored = raw ? JSON.parse(raw) : { version: 1, resource: identity.resource, redirectUrl: "" };
|
|
53
|
+
if (stored.version !== 1 || stored.resource !== identity.resource)
|
|
54
|
+
throw new Error("Cloud credentials are invalid. Run frely cloud logout.");
|
|
55
|
+
const state = randomUUID();
|
|
56
|
+
let verifier = "";
|
|
57
|
+
let listener;
|
|
58
|
+
let timer;
|
|
59
|
+
let resolveCode;
|
|
60
|
+
let rejectCode;
|
|
61
|
+
let pendingCode;
|
|
62
|
+
const closeListener = async () => {
|
|
63
|
+
if (timer)
|
|
64
|
+
clearTimeout(timer);
|
|
65
|
+
if (listener?.listening)
|
|
66
|
+
await new Promise(resolve => listener.close(() => resolve()));
|
|
67
|
+
};
|
|
68
|
+
const listen = async (port) => {
|
|
69
|
+
listener = createServer((request, response) => {
|
|
70
|
+
const url = new URL(request.url ?? "/", stored.redirectUrl || "http://127.0.0.1");
|
|
71
|
+
if (url.pathname !== "/callback" || url.searchParams.get("state") !== state) {
|
|
72
|
+
response.writeHead(400);
|
|
73
|
+
response.end("Invalid authorization callback.");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const code = url.searchParams.get("code");
|
|
77
|
+
response.setHeader("content-type", "text/plain; charset=utf-8");
|
|
78
|
+
response.setHeader("cache-control", "no-store");
|
|
79
|
+
if (!code || url.searchParams.has("error")) {
|
|
80
|
+
response.writeHead(400);
|
|
81
|
+
response.end("Authorization was not completed.");
|
|
82
|
+
rejectCode?.(new Error("Cloud authorization was declined."));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
response.end("Frely Cloud is authorized. You can close this window.");
|
|
86
|
+
resolveCode?.(code);
|
|
87
|
+
});
|
|
88
|
+
await new Promise((resolve, reject) => {
|
|
89
|
+
listener.once("error", reject);
|
|
90
|
+
listener.listen(port, "127.0.0.1", resolve);
|
|
91
|
+
});
|
|
92
|
+
const address = listener.address();
|
|
93
|
+
if (!address || typeof address === "string")
|
|
94
|
+
throw new Error("Cloud callback could not start.");
|
|
95
|
+
return "http://127.0.0.1:" + address.port + "/callback";
|
|
96
|
+
};
|
|
97
|
+
if (!stored.redirectUrl)
|
|
98
|
+
stored.redirectUrl = await listen(0);
|
|
99
|
+
const callback = new URL(stored.redirectUrl);
|
|
100
|
+
if (callback.protocol !== "http:" || callback.hostname !== "127.0.0.1" || callback.pathname !== "/callback" || !callback.port || callback.username || callback.password || callback.search || callback.hash) {
|
|
101
|
+
await closeListener();
|
|
102
|
+
throw new Error("Stored Cloud callback is invalid.");
|
|
103
|
+
}
|
|
104
|
+
const save = () => credentialStore.setPassword(SERVICE, identity.key, JSON.stringify(stored));
|
|
105
|
+
const provider = {
|
|
106
|
+
redirectUrl: stored.redirectUrl,
|
|
107
|
+
clientMetadata: { client_name: "Frely CLI Cloud", redirect_uris: [stored.redirectUrl],
|
|
108
|
+
grant_types: ["authorization_code", "refresh_token"], response_types: ["code"], token_endpoint_auth_method: "none", scope: SCOPE },
|
|
109
|
+
state: () => state,
|
|
110
|
+
clientInformation: () => stored.client,
|
|
111
|
+
saveClientInformation: async (client) => { stored.client = client; await save(); },
|
|
112
|
+
tokens: () => stored.tokens,
|
|
113
|
+
saveTokens: async (tokens) => {
|
|
114
|
+
// This checks account selection; signature/audience verification remains on the server.
|
|
115
|
+
if (identity.userId) {
|
|
116
|
+
let subject;
|
|
117
|
+
try {
|
|
118
|
+
subject = JSON.parse(Buffer.from(tokens.access_token.split(".")[1] ?? "", "base64url").toString()).sub;
|
|
119
|
+
}
|
|
120
|
+
catch { /* Rejected below. */ }
|
|
121
|
+
if (subject !== identity.userId)
|
|
122
|
+
throw new Error("Cloud authorization used another account. Use the account shown by frely whoami.");
|
|
123
|
+
}
|
|
124
|
+
stored.tokens = tokens;
|
|
125
|
+
stored.expiresAt = Date.now() + (tokens.expires_in ?? 600) * 1000;
|
|
126
|
+
await save();
|
|
127
|
+
},
|
|
128
|
+
saveCodeVerifier: value => { verifier = value; },
|
|
129
|
+
codeVerifier: () => { if (!verifier)
|
|
130
|
+
throw new Error("Cloud PKCE verifier is missing."); return verifier; },
|
|
131
|
+
redirectToAuthorization: async (url) => {
|
|
132
|
+
if (url.origin !== identity.origin)
|
|
133
|
+
throw new Error("Unexpected Cloud authorization server.");
|
|
134
|
+
if (!listener)
|
|
135
|
+
await listen(Number(callback.port));
|
|
136
|
+
pendingCode = new Promise((resolve, reject) => { resolveCode = resolve; rejectCode = reject; });
|
|
137
|
+
// Attach immediately so a callback rejection never becomes an unhandled promise.
|
|
138
|
+
pendingCode.catch(() => undefined);
|
|
139
|
+
timer = setTimeout(() => rejectCode?.(new Error("Cloud authorization timed out.")), 300000);
|
|
140
|
+
process.stderr.write("Authorize Frely Cloud in your browser:\n" + url.toString() + "\n");
|
|
141
|
+
openVerificationUrl(url.toString());
|
|
142
|
+
},
|
|
143
|
+
validateResourceURL: async (_serverUrl, resource) => {
|
|
144
|
+
if (resource !== undefined && resource !== identity.resource)
|
|
145
|
+
throw new Error("Cloud resource mismatch.");
|
|
146
|
+
return new URL(identity.resource);
|
|
147
|
+
},
|
|
148
|
+
invalidateCredentials: async (scope) => {
|
|
149
|
+
if (scope === "all" || scope === "client")
|
|
150
|
+
delete stored.client;
|
|
151
|
+
if (scope === "all" || scope === "tokens") {
|
|
152
|
+
delete stored.tokens;
|
|
153
|
+
delete stored.expiresAt;
|
|
154
|
+
}
|
|
155
|
+
if (scope === "all" || scope === "verifier")
|
|
156
|
+
verifier = "";
|
|
157
|
+
await save();
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
const cloudFetch = async (input, init) => {
|
|
161
|
+
const url = new URL(input instanceof Request ? input.url : input.toString());
|
|
162
|
+
if (url.origin !== identity.origin)
|
|
163
|
+
throw new Error("Cloud discovery cannot send credentials to another origin.");
|
|
164
|
+
return fetch(input, { ...init, redirect: "error", signal: init?.signal
|
|
165
|
+
? AbortSignal.any([init.signal, AbortSignal.timeout(180000)]) : AbortSignal.timeout(180000) });
|
|
166
|
+
};
|
|
167
|
+
const transport = new StreamableHTTPClientTransport(new URL(identity.resource), {
|
|
168
|
+
authProvider: provider, fetch: cloudFetch, reconnectionOptions: { maxRetries: 0, initialReconnectionDelay: 1000, maxReconnectionDelay: 1000, reconnectionDelayGrowFactor: 1 },
|
|
169
|
+
});
|
|
170
|
+
let client = new Client({ name: "frely-cli-cloud", version: VERSION });
|
|
171
|
+
try {
|
|
172
|
+
try {
|
|
173
|
+
await client.connect(transport);
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
if (!(error instanceof UnauthorizedError) || !pendingCode)
|
|
177
|
+
throw error;
|
|
178
|
+
await transport.finishAuth(await pendingCode);
|
|
179
|
+
client = new Client({ name: "frely-cli-cloud", version: VERSION });
|
|
180
|
+
await client.connect(transport);
|
|
181
|
+
}
|
|
182
|
+
await closeListener();
|
|
183
|
+
return { client, close: () => client.close() };
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
await closeListener();
|
|
187
|
+
await client.close().catch(() => undefined);
|
|
188
|
+
throw new Error("Cloud connection or authorization failed. Confirm app availability and account selection, then run frely cloud login. No business call was replayed.");
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
export async function runCloud(args) {
|
|
192
|
+
const action = args[1] ?? "list";
|
|
193
|
+
if (action === "help" || args.includes("--help") || args.includes("-h"))
|
|
194
|
+
return { text: CLOUD_USAGE };
|
|
195
|
+
if (!["list", "describe", "call", "login", "logout"].includes(action))
|
|
196
|
+
throw new Error(CLOUD_USAGE);
|
|
197
|
+
const named = action === "describe" || action === "call";
|
|
198
|
+
const name = named ? args[2] : undefined;
|
|
199
|
+
if (named && (!name || !/^[a-zA-Z0-9_.-]{1,128}$/.test(name)))
|
|
200
|
+
throw new Error("A valid Cloud tool name is required.");
|
|
201
|
+
const options = new Map();
|
|
202
|
+
for (let i = named ? 3 : 2; i < args.length; i++) {
|
|
203
|
+
const option = args[i], value = args[++i];
|
|
204
|
+
const allowed = action === "list" ? ["--group"] : action === "call" ? ["--json", "--input"] : [];
|
|
205
|
+
if (!allowed.includes(option) || options.has(option) || value === undefined)
|
|
206
|
+
throw new Error(CLOUD_USAGE);
|
|
207
|
+
options.set(option, value);
|
|
208
|
+
}
|
|
209
|
+
let input = {};
|
|
210
|
+
if (options.has("--json") && options.has("--input"))
|
|
211
|
+
throw new Error("Use --json or --input.");
|
|
212
|
+
if (action === "call") {
|
|
213
|
+
let raw = options.get("--json") ?? "{}";
|
|
214
|
+
const file = options.get("--input");
|
|
215
|
+
if (file !== undefined) {
|
|
216
|
+
if ((await stat(file)).size > 512 * 1024)
|
|
217
|
+
throw new Error("Cloud input exceeds 512 KiB.");
|
|
218
|
+
raw = await readFile(file, "utf8");
|
|
219
|
+
}
|
|
220
|
+
if (Buffer.byteLength(raw) > 512 * 1024)
|
|
221
|
+
throw new Error("Cloud input exceeds 512 KiB.");
|
|
222
|
+
const value = JSON.parse(raw);
|
|
223
|
+
if (!value || Array.isArray(value) || typeof value !== "object")
|
|
224
|
+
throw new Error("Cloud input must be a JSON object.");
|
|
225
|
+
input = value;
|
|
226
|
+
}
|
|
227
|
+
if (action === "logout") {
|
|
228
|
+
await logoutCloud();
|
|
229
|
+
return { value: { authorized: false } };
|
|
230
|
+
}
|
|
231
|
+
const session = await connectCloud();
|
|
232
|
+
try {
|
|
233
|
+
if (action === "login")
|
|
234
|
+
return { value: { authorized: true } };
|
|
235
|
+
const all = [];
|
|
236
|
+
const cursors = new Set();
|
|
237
|
+
let cursor;
|
|
238
|
+
do {
|
|
239
|
+
const page = await session.client.listTools(cursor === undefined ? {} : { cursor });
|
|
240
|
+
all.push(...page.tools);
|
|
241
|
+
cursor = page.nextCursor;
|
|
242
|
+
if (cursor && (cursors.has(cursor) || cursors.size >= 100))
|
|
243
|
+
throw new Error("Invalid Cloud tool pagination.");
|
|
244
|
+
if (cursor)
|
|
245
|
+
cursors.add(cursor);
|
|
246
|
+
} while (cursor);
|
|
247
|
+
if (action === "list") {
|
|
248
|
+
const group = options.get("--group");
|
|
249
|
+
return { value: { tools: all.filter(tool => !group || tool.name.startsWith(group + ".")) } };
|
|
250
|
+
}
|
|
251
|
+
const tool = all.find(tool => tool.name === name);
|
|
252
|
+
if (!tool)
|
|
253
|
+
throw new Error("Cloud tool is unavailable or not authorized: " + name);
|
|
254
|
+
if (action === "describe")
|
|
255
|
+
return { value: tool };
|
|
256
|
+
const result = await session.client.callTool({ name: name, arguments: input }, undefined, { timeout: 180000 });
|
|
257
|
+
return { value: result, failed: result.isError === true };
|
|
258
|
+
}
|
|
259
|
+
finally {
|
|
260
|
+
await session.close();
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=cloud.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud.js","sourceRoot":"","sources":["../src/cloud.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type DeviceBinding } from "./state.js";
|
|
2
|
+
export declare const HEARTBEAT_MAX_AGE_MS = 75000;
|
|
3
|
+
export interface ConnectionStatus {
|
|
4
|
+
version: 1;
|
|
5
|
+
cliVersion?: string;
|
|
6
|
+
autoRefresh?: boolean;
|
|
7
|
+
entry?: string;
|
|
8
|
+
startedAt?: string;
|
|
9
|
+
pid: number;
|
|
10
|
+
relayUrl: string;
|
|
11
|
+
userId: string;
|
|
12
|
+
deviceId: string;
|
|
13
|
+
workspace?: string;
|
|
14
|
+
authorizationId?: string | undefined;
|
|
15
|
+
mcpEnabled: boolean;
|
|
16
|
+
state: "connecting" | "connected" | "disconnected" | "stopped";
|
|
17
|
+
updatedAt: string;
|
|
18
|
+
connectedAt?: string | undefined;
|
|
19
|
+
heartbeatAt?: string | undefined;
|
|
20
|
+
lastError?: string;
|
|
21
|
+
}
|
|
22
|
+
export type ConnectionEvent = {
|
|
23
|
+
type: "upgrade_watch";
|
|
24
|
+
enabled: boolean;
|
|
25
|
+
} | {
|
|
26
|
+
type: "connecting";
|
|
27
|
+
authorizationId?: string | undefined;
|
|
28
|
+
mcpEnabled: boolean;
|
|
29
|
+
} | {
|
|
30
|
+
type: "connected" | "heartbeat" | "mcp_disabled" | "stopped";
|
|
31
|
+
} | {
|
|
32
|
+
type: "disconnected" | "authorization_unavailable";
|
|
33
|
+
error: unknown;
|
|
34
|
+
};
|
|
35
|
+
export declare function connectionStatusPath(): string;
|
|
36
|
+
/** Observability must never interrupt tool execution or serialize credentials/errors verbatim. */
|
|
37
|
+
export declare function connectionReporter(binding: DeviceBinding, workspace?: string): {
|
|
38
|
+
report: (event: ConnectionEvent) => void;
|
|
39
|
+
flush: () => Promise<void>;
|
|
40
|
+
};
|
|
41
|
+
export declare function readConnectionStatus(binding: DeviceBinding): Promise<ConnectionStatus | null>;
|
|
42
|
+
export declare function connectionIsLive(status: ConnectionStatus, now?: number): boolean;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { VERSION } from "../version.js";
|
|
2
|
+
import { IS_STANDALONE } from "../cli-launch.js";
|
|
3
|
+
import { realpathSync } from "node:fs";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
6
|
+
import { dirname, join } from "node:path";
|
|
7
|
+
import { deviceStatePath } from "./state.js";
|
|
8
|
+
import { diagnosticError } from "../runtime/diagnostics.js";
|
|
9
|
+
export const HEARTBEAT_MAX_AGE_MS = 75_000;
|
|
10
|
+
export function connectionStatusPath() {
|
|
11
|
+
return join(dirname(deviceStatePath()), "relay-status-v1.json");
|
|
12
|
+
}
|
|
13
|
+
/** Observability must never interrupt tool execution or serialize credentials/errors verbatim. */
|
|
14
|
+
export function connectionReporter(binding, workspace) {
|
|
15
|
+
let current = {
|
|
16
|
+
version: 1, cliVersion: VERSION, entry: realpathSync(IS_STANDALONE ? process.execPath : process.argv[1]), startedAt: new Date().toISOString(), pid: process.pid, relayUrl: binding.relayUrl, userId: binding.userId,
|
|
17
|
+
deviceId: binding.deviceId, ...(workspace ? { workspace } : {}),
|
|
18
|
+
mcpEnabled: false, state: "connecting", updatedAt: new Date().toISOString(),
|
|
19
|
+
};
|
|
20
|
+
let pending = Promise.resolve();
|
|
21
|
+
const path = connectionStatusPath();
|
|
22
|
+
const report = (event) => {
|
|
23
|
+
const now = new Date().toISOString();
|
|
24
|
+
current = { ...current, updatedAt: now };
|
|
25
|
+
if (event.type === "upgrade_watch") {
|
|
26
|
+
current = { ...current, autoRefresh: event.enabled };
|
|
27
|
+
}
|
|
28
|
+
else if (event.type === "connecting") {
|
|
29
|
+
current = { ...current, state: "connecting", mcpEnabled: event.mcpEnabled,
|
|
30
|
+
authorizationId: event.authorizationId, heartbeatAt: undefined, connectedAt: undefined };
|
|
31
|
+
}
|
|
32
|
+
else if (event.type === "connected") {
|
|
33
|
+
current = { ...current, state: "connected", connectedAt: now };
|
|
34
|
+
}
|
|
35
|
+
else if (event.type === "heartbeat") {
|
|
36
|
+
current = { ...current, heartbeatAt: now };
|
|
37
|
+
}
|
|
38
|
+
else if (event.type === "mcp_disabled") {
|
|
39
|
+
current = { ...current, mcpEnabled: false };
|
|
40
|
+
}
|
|
41
|
+
else if (event.type === "disconnected" || event.type === "authorization_unavailable") {
|
|
42
|
+
const error = diagnosticError(event.error);
|
|
43
|
+
current = { ...current, ...(event.type === "disconnected" ? { state: "disconnected" } : {}), mcpEnabled: false,
|
|
44
|
+
lastError: [error.code, error.message].filter(Boolean).join(": ") };
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
current = { ...current, state: "stopped", mcpEnabled: false };
|
|
48
|
+
}
|
|
49
|
+
const content = JSON.stringify(current) + "\n";
|
|
50
|
+
pending = pending.then(async () => {
|
|
51
|
+
const temp = path + "." + process.pid + "." + randomUUID() + ".tmp";
|
|
52
|
+
try {
|
|
53
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
54
|
+
await writeFile(temp, content, { flag: "wx", mode: 0o600 });
|
|
55
|
+
await rename(temp, path);
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
await rm(temp, { force: true }).catch(() => undefined);
|
|
59
|
+
}
|
|
60
|
+
}).catch(() => undefined);
|
|
61
|
+
};
|
|
62
|
+
return { report, flush: () => pending };
|
|
63
|
+
}
|
|
64
|
+
export async function readConnectionStatus(binding) {
|
|
65
|
+
const raw = await readFile(connectionStatusPath(), "utf8").catch(() => null);
|
|
66
|
+
if (!raw)
|
|
67
|
+
return null;
|
|
68
|
+
let value;
|
|
69
|
+
try {
|
|
70
|
+
value = JSON.parse(raw);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
if (!value || value.version !== 1 || value.relayUrl !== binding.relayUrl || value.userId !== binding.userId
|
|
76
|
+
|| value.deviceId !== binding.deviceId || !Number.isSafeInteger(value.pid) || value.pid <= 0
|
|
77
|
+
|| !["connecting", "connected", "disconnected", "stopped"].includes(value.state)
|
|
78
|
+
|| typeof value.mcpEnabled !== "boolean" || !Number.isFinite(Date.parse(value.updatedAt))
|
|
79
|
+
|| (value.heartbeatAt !== undefined && !Number.isFinite(Date.parse(value.heartbeatAt)))
|
|
80
|
+
|| (value.connectedAt !== undefined && !Number.isFinite(Date.parse(value.connectedAt)))
|
|
81
|
+
|| (value.workspace !== undefined && typeof value.workspace !== "string")
|
|
82
|
+
|| (value.authorizationId !== undefined && !/^mca_[a-f0-9]{32}$/u.test(value.authorizationId)))
|
|
83
|
+
return null;
|
|
84
|
+
// Return only known fields; never print arbitrary content from a diagnostic file.
|
|
85
|
+
return { version: 1,
|
|
86
|
+
...(typeof value.autoRefresh === "boolean" ? { autoRefresh: value.autoRefresh } : {}),
|
|
87
|
+
...(typeof value.cliVersion === "string" ? { cliVersion: value.cliVersion.slice(0, 80) } : {}),
|
|
88
|
+
...(typeof value.entry === "string" ? { entry: value.entry } : {}),
|
|
89
|
+
...(typeof value.startedAt === "string" ? { startedAt: value.startedAt } : {}),
|
|
90
|
+
pid: value.pid, relayUrl: binding.relayUrl, userId: binding.userId, deviceId: binding.deviceId,
|
|
91
|
+
state: value.state, mcpEnabled: value.mcpEnabled, updatedAt: value.updatedAt,
|
|
92
|
+
...(value.workspace ? { workspace: value.workspace } : {}),
|
|
93
|
+
...(value.authorizationId ? { authorizationId: value.authorizationId } : {}),
|
|
94
|
+
...(value.heartbeatAt ? { heartbeatAt: value.heartbeatAt } : {}),
|
|
95
|
+
...(value.connectedAt ? { connectedAt: value.connectedAt } : {}),
|
|
96
|
+
...(typeof value.lastError === "string" ? { lastError: value.lastError.slice(0, 240) } : {}) };
|
|
97
|
+
}
|
|
98
|
+
export function connectionIsLive(status, now = Date.now()) {
|
|
99
|
+
if (status.state !== "connected" || !status.heartbeatAt)
|
|
100
|
+
return false;
|
|
101
|
+
const age = now - Date.parse(status.heartbeatAt);
|
|
102
|
+
if (!Number.isFinite(age) || age < 0 || age > HEARTBEAT_MAX_AGE_MS)
|
|
103
|
+
return false;
|
|
104
|
+
try {
|
|
105
|
+
process.kill(status.pid, 0);
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
return error.code === "EPERM";
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=connection-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-status.js","sourceRoot":"","sources":["../../src/device/connection-status.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { MaintenanceGate } from "../upgrade/maintenance.js";
|
|
1
2
|
import { McpLease } from "../runtime/mcp-lease.js";
|
|
3
|
+
import { type ConnectionEvent } from "./connection-status.js";
|
|
2
4
|
import { RelayMcpSession } from "../runtime/relay-mcp.js";
|
|
3
5
|
export interface RelayServeOptions {
|
|
4
6
|
workspace?: string;
|
|
7
|
+
managedService?: boolean;
|
|
8
|
+
restartForUpgrade?: () => void;
|
|
5
9
|
signal: AbortSignal;
|
|
6
10
|
log?: (message: string) => void;
|
|
7
11
|
}
|
|
8
12
|
export declare function serveDeviceRelay(options: RelayServeOptions): Promise<void>;
|
|
9
|
-
export declare function serveConnection(websocketUrl: string, accessToken: string, deviceId: string, session: RelayMcpSession | null, lease: McpLease | null, signal: AbortSignal, log: (message: string) => void): Promise<void>;
|
|
13
|
+
export declare function serveConnection(websocketUrl: string, accessToken: string, deviceId: string, session: RelayMcpSession | null, lease: McpLease | null, signal: AbortSignal, log: (message: string) => void, report?: (event: ConnectionEvent) => void, maintenance?: MaintenanceGate): Promise<void>;
|