frely-cli 0.8.4 → 0.9.2
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 +11 -10
- package/README.zh-CN.md +11 -10
- package/dist/agent/app-install.d.ts +5 -9
- package/dist/agent/app-install.js +22 -36
- package/dist/agent/app-install.js.map +1 -1
- package/dist/agent/supervisor.js +1 -1
- package/dist/agent/supervisor.js.map +1 -1
- package/dist/agent-help.d.ts +131 -18
- package/dist/agent-help.js +29 -10
- package/dist/agent-help.js.map +1 -1
- package/dist/app-manager.d.ts +75 -0
- package/dist/app-manager.js +360 -0
- package/dist/app-manager.js.map +1 -0
- package/dist/diagnostics.js +20 -11
- package/dist/diagnostics.js.map +1 -1
- package/dist/index.js +68 -10
- package/dist/index.js.map +1 -1
- package/dist/mcp-authorization.d.ts +11 -1
- package/dist/mcp-authorization.js +56 -14
- package/dist/mcp-authorization.js.map +1 -1
- package/dist/mcp-command.d.ts +4 -3
- package/dist/mcp-command.js +20 -16
- package/dist/mcp-command.js.map +1 -1
- package/dist/runtime/mcp-lease.js +1 -1
- package/dist/runtime/mcp-lease.js.map +1 -1
- package/dist/workspace-command.d.ts +1 -1
- package/dist/workspace-command.js +3 -3
- package/dist/workspace-command.js.map +1 -1
- package/package.json +1 -1
package/dist/agent-help.js
CHANGED
|
@@ -5,8 +5,10 @@ export const COMMANDS = [
|
|
|
5
5
|
{ id: "doctor", usage: "frely doctor [-v] [--json]", auth: "optional-account", effect: "diagnostic", purpose: "Show the signed-in account, installation, available upgrades, MCP and connection status; -v verifies the account online and runs detailed diagnostics." },
|
|
6
6
|
{ id: "upgrade", usage: "frely upgrade", auth: "none", effect: "local-write", purpose: "Upgrade the current installation to the latest stable release. Windows prints a manual command; doctor checks versions." },
|
|
7
7
|
{ id: "help", usage: "frely help --agent --json", auth: "none", effect: "read", purpose: "Read this installed CLI's current Agent instructions." },
|
|
8
|
-
{ id: "mcp", usage: "frely mcp [--workspace <path>] [--days 1..180] [--json]", auth: "account-and-browser-if-needed", effect: "authorization-if-needed", purpose: "Enable, renew or read device MCP. Unconfigured: request browser approval for --workspace (default: current directory) and install the background service. Expired or --days given: renew with browser approval; the MCP URL stays the same. Otherwise print the MCP URL unchanged. Prompts go to stderr; stdout holds only the URL, or JSON with HTTP transport and OAuth details." },
|
|
9
|
-
{ id: "mcp.workspace", usage: "frely mcp workspace
|
|
8
|
+
{ id: "mcp.url", usage: "frely mcp url [--workspace <path>] [--days 1..180] [--json]", auth: "account-and-browser-if-needed", effect: "authorization-if-needed", purpose: "Enable, renew or read device MCP. Unconfigured: request browser approval for --workspace (default: current directory) and install the background service. Expired or --days given: renew with browser approval; the MCP URL stays the same. Otherwise print the MCP URL unchanged. Prompts go to stderr; stdout holds only the URL, or JSON with HTTP transport and OAuth details." },
|
|
9
|
+
{ id: "mcp.workspace.list", usage: "frely mcp workspace list [--json]", auth: "mcp", effect: "read", purpose: "List workspace directories for this device; the primary is marked." },
|
|
10
|
+
{ id: "mcp.workspace.add", usage: "frely mcp workspace add <path>", auth: "mcp", effect: "local-write", purpose: "Add an additional workspace directory for this device." },
|
|
11
|
+
{ id: "mcp.workspace.remove", usage: "frely mcp workspace remove <path>", auth: "mcp", effect: "local-write", purpose: "Remove an additional workspace directory (the primary cannot be removed)." },
|
|
10
12
|
{ id: "mcp.stop", usage: "frely mcp stop", auth: "none", effect: "local-service", purpose: "Pause the local MCP background service. Supported upgrades restore running services without this command." },
|
|
11
13
|
{ id: "mcp.start", usage: "frely mcp start", auth: "none", effect: "local-service", purpose: "Resume the local MCP background service." },
|
|
12
14
|
{ id: "mcp.remove", usage: "frely mcp remove", auth: "account", effect: "remote-write", purpose: "Revoke device MCP for every connected client and uninstall the background service (kept running provider-only when local Providers exist)." },
|
|
@@ -19,11 +21,18 @@ export const COMMANDS = [
|
|
|
19
21
|
{ id: "provider.share", usage: "frely provider share [ollama|openai-compatible] [--url <loopback-v1-url>] [--models <a,b>] [--slot <slot-id>] [--name <name>]", auth: "account", effect: "remote-write", purpose: "Publish a local model Provider. If a prepared Provider on this device is not finished, resume it instead." },
|
|
20
22
|
{ id: "provider.list", usage: "frely provider list [--json]", auth: "account", effect: "read", purpose: "List configured local Providers." },
|
|
21
23
|
{ id: "cloud", usage: "frely cloud list|describe|call [--help]", auth: "cloud-oauth", effect: "subcommand-dependent", purpose: "Discover and call Frely cloud business operations at frely.cloud/mcp. The first call requests browser authorization. Use describe before call; parameters and results are JSON." },
|
|
22
|
-
{ id: "app.remote", usage: "frely app remote enable
|
|
24
|
+
{ id: "app.remote.enable", usage: "frely app remote enable", auth: "local", effect: "local-write", purpose: "Allow agent remote control from the Frely web app (app.frely.cloud). Disabled by default; enable before starting tasks from a phone." },
|
|
25
|
+
{ id: "app.remote.disable", usage: "frely app remote disable", auth: "local", effect: "local-write", purpose: "Disallow agent remote control from the Frely web app." },
|
|
26
|
+
{ id: "app.remote.status", usage: "frely app remote status [--json]", auth: "local", effect: "read", purpose: "Show whether agent remote control is enabled and the task budget limits." },
|
|
23
27
|
{ id: "app.ops", usage: "frely app ops", auth: "local", effect: "read-only", purpose: "Bridge the local agent ops socket to stdin/stdout (NDJSON, incl. tasks_changed pushes); used by the Frely App GUI task panel." },
|
|
24
28
|
{ id: "app.connectInfo", usage: "frely app connect-info [--json]", auth: "local", effect: "read-only", purpose: "Report the local agent ops socket path and whether a serving process is reachable (used by the Frely App GUI to find task control)." },
|
|
25
29
|
{ id: "app.key", usage: "frely app key [--lifetime-usd N] [--json]", auth: "user", effect: "account-write", purpose: "Provision a device-scoped Frely API key for app agent tasks (shown once, capped at a lifetime spend limit; default $50, max $500)." },
|
|
26
30
|
{ id: "app.tasks", usage: "frely app tasks [--json]", auth: "local", effect: "read", purpose: "List local agent tasks with status, merge state and budget usage." },
|
|
31
|
+
{ id: "app.install", usage: "frely app install [--force] [--json]", auth: "local", effect: "local-write", purpose: "Install the Frely App: Homebrew cask when available, otherwise a verified download (SHA-256) from the FrelyHQ/frely-cli release mirror; quarantine is preserved." },
|
|
32
|
+
{ id: "app.open", usage: "frely app open [--window]", auth: "local", effect: "local-write", purpose: "Launch the Frely App in the background (menu bar) or with its main window via --window." },
|
|
33
|
+
{ id: "app.status", usage: "frely app status [--json]", auth: "local", effect: "read", purpose: "Show whether the Frely App is installed, its version, install path, running state and how it is managed." },
|
|
34
|
+
{ id: "app.update", usage: "frely app update [--json]", auth: "local", effect: "local-write", purpose: "Update the Frely App through Homebrew or by re-downloading the latest release." },
|
|
35
|
+
{ id: "app.uninstall", usage: "frely app uninstall", auth: "local", effect: "local-write", purpose: "Uninstall the Frely App. Tasks, credentials and worktrees stay with frely-cli." },
|
|
27
36
|
{ id: "network", usage: "frely network setup|status|find|use|logout [--json]", auth: "network", effect: "subcommand-dependent", purpose: "Access Frely Network (preview) using its separate setup and credentials." },
|
|
28
37
|
];
|
|
29
38
|
export function agentHelp() {
|
|
@@ -42,8 +51,8 @@ export function agentHelp() {
|
|
|
42
51
|
"Budget sources are independent constraints. Do not sum their remaining amounts or describe them as a Key balance.",
|
|
43
52
|
"Installing a remote Agent Skill does not replace the host's current model provider.",
|
|
44
53
|
"Device MCP exposes this computer to remote HTTP MCP clients with OAuth. Commands execute on the device, not on the calling computer.",
|
|
45
|
-
"Use frely mcp to enable device MCP or read its address, and frely doctor [-v] for status and diagnostics.",
|
|
46
|
-
"If MCP is unconfigured or expired, frely mcp requests browser approval; otherwise it only prints the URL. Existing workspaces stay unchanged.",
|
|
54
|
+
"Use frely mcp url to enable device MCP or read its address, and frely doctor [-v] for status and diagnostics.",
|
|
55
|
+
"If MCP is unconfigured or expired, frely mcp url requests browser approval; otherwise it only prints the URL. Existing workspaces stay unchanged.",
|
|
47
56
|
"Remote clients of one device share its workspace and managed processes. Shell uses the device OS account; it is not a workspace sandbox.",
|
|
48
57
|
],
|
|
49
58
|
commands: COMMANDS,
|
|
@@ -51,7 +60,7 @@ export function agentHelp() {
|
|
|
51
60
|
}
|
|
52
61
|
const GROUPS = [
|
|
53
62
|
{ title: "Account", ids: ["login", "logout", "doctor", "upgrade"] },
|
|
54
|
-
{ title: "Device MCP", ids: ["mcp", "mcp.workspace", "mcp.lifecycle"] },
|
|
63
|
+
{ title: "Device MCP", ids: ["mcp.url", "mcp.workspace", "mcp.lifecycle"] },
|
|
55
64
|
{ title: "Agents", ids: ["agent.install", "agent.run", "agent.status", "agent.remove"] },
|
|
56
65
|
{ title: "Providers", ids: ["provider.share", "provider.list"] },
|
|
57
66
|
{ title: "Cloud", ids: ["cloud"] },
|
|
@@ -65,8 +74,8 @@ const SHORT_USAGE = {
|
|
|
65
74
|
logout: "frely logout",
|
|
66
75
|
doctor: "frely doctor [-v] [--json]",
|
|
67
76
|
upgrade: "frely upgrade",
|
|
68
|
-
mcp: "frely mcp [--workspace <path>] [--days 1..180] [--json]",
|
|
69
|
-
"mcp.workspace": "frely mcp workspace
|
|
77
|
+
"mcp.url": "frely mcp url [--workspace <path>] [--days 1..180] [--json]",
|
|
78
|
+
"mcp.workspace": "frely mcp workspace list|add <path>|remove <path>",
|
|
70
79
|
"mcp.lifecycle": "frely mcp stop|start|remove",
|
|
71
80
|
"agent.install": "frely agent install <distribution-id> [--host <host>] [--api-key-stdin]",
|
|
72
81
|
"agent.run": "frely agent run <distribution-id> (--input <text>|--input-stdin)",
|
|
@@ -86,11 +95,21 @@ export function cliUsage() {
|
|
|
86
95
|
lines.push("\nFull flags and the machine-readable contract: frely help --agent --json\n");
|
|
87
96
|
return lines.join("");
|
|
88
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* A command group without a direct action (`frely mcp workspace`, `frely agent`,
|
|
100
|
+
* ...) prints the subcommands under it instead of running one.
|
|
101
|
+
*/
|
|
102
|
+
export function subcommandUsage(group) {
|
|
103
|
+
const prefix = `${group}.`;
|
|
104
|
+
const lines = COMMANDS.filter((command) => command.id.startsWith(prefix))
|
|
105
|
+
.map((command) => ` ${SHORT_USAGE[command.id] ?? command.usage}\n`);
|
|
106
|
+
return `Usage:\n${lines.join("")}`;
|
|
107
|
+
}
|
|
89
108
|
export function mcpUsage() {
|
|
90
109
|
return "Device MCP — use this computer from a remote MCP client.\n\nUsage:\n"
|
|
91
|
-
+ ["mcp", "mcp.workspace", "mcp.lifecycle"].map((id) => " " + SHORT_USAGE[id] + "\n").join("")
|
|
110
|
+
+ ["mcp.url", "mcp.workspace", "mcp.lifecycle"].map((id) => " " + SHORT_USAGE[id] + "\n").join("")
|
|
92
111
|
+ "\nStatus and diagnostics: frely doctor [-v] [--json]\n\n"
|
|
93
|
-
+ "Run frely mcp on the computer to control. It asks for browser approval the first time (current directory, or --workspace) and when authorization has expired, installs the background service, and prints the MCP URL. Add that URL to ChatGPT, Claude Code on another computer, or another HTTP MCP client, then authorize with OAuth.\n"
|
|
112
|
+
+ "Run frely mcp url on the computer to control. It asks for browser approval the first time (current directory, or --workspace) and when authorization has expired, installs the background service, and prints the MCP URL. Add that URL to ChatGPT, Claude Code on another computer, or another HTTP MCP client, then authorize with OAuth.\n"
|
|
94
113
|
+ "Prompts go to stderr; stdout contains only the URL or JSON. --days 1..180 renews now; the URL stays the same.\n"
|
|
95
114
|
+ "frely mcp remove revokes access for every client. Clients share the device workspace and managed processes. Shell runs under the device OS account.\n";
|
|
96
115
|
}
|
package/dist/agent-help.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-help.js","sourceRoot":"","sources":["../src/agent-help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,4CAA4C,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,iDAAiD,EAAE;IAC1K,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,+EAA+E,EAAE;IACtK,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,4BAA4B,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,wJAAwJ,EAAE;IACxQ,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,yHAAyH,EAAE;IAClN,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,2BAA2B,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,uDAAuD,EAAE;IAClJ,EAAE,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"agent-help.js","sourceRoot":"","sources":["../src/agent-help.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `frely app install|open|status|update|uninstall` — install and manage the
|
|
3
|
+
* Frely App (GUI) from the frely-cli side (architecture doc §8.2).
|
|
4
|
+
*
|
|
5
|
+
* Distribution facts (tool/release_contract.mjs in the app repository):
|
|
6
|
+
* - public release mirror: github.com/FrelyHQ/frely-cli (the private source
|
|
7
|
+
* repository never serves downloads directly)
|
|
8
|
+
* - release tags: `frely-app-v<version>` (legacy `frely-client-v<version>`)
|
|
9
|
+
* - asset names: `Frely-App-<version>-<label>.<ext>` (legacy `Pi-Client-…`)
|
|
10
|
+
* - Homebrew: `brew install --cask frelyhq/tap/frely-app`
|
|
11
|
+
*/
|
|
12
|
+
export type AppAsset = {
|
|
13
|
+
name: string;
|
|
14
|
+
url: string;
|
|
15
|
+
size: number;
|
|
16
|
+
};
|
|
17
|
+
export type AppRelease = {
|
|
18
|
+
tag: string;
|
|
19
|
+
version: string;
|
|
20
|
+
prerelease: boolean;
|
|
21
|
+
assets: AppAsset[];
|
|
22
|
+
};
|
|
23
|
+
export type AppInstallStatus = {
|
|
24
|
+
installed: boolean;
|
|
25
|
+
path?: string;
|
|
26
|
+
version?: string;
|
|
27
|
+
running: boolean;
|
|
28
|
+
managedBy: "homebrew" | "manual" | "none";
|
|
29
|
+
};
|
|
30
|
+
export declare const DISTRIBUTION_REPO = "FrelyHQ/frely-cli";
|
|
31
|
+
export declare const TAG_PREFIXES: readonly ["frely-app-v", "frely-client-v"];
|
|
32
|
+
export declare const ASSET_PREFIXES: readonly ["Frely-App-", "Pi-Client-"];
|
|
33
|
+
export declare const HOMEBREW_CASK = "frely-app";
|
|
34
|
+
export declare const HOMEBREW_LEGACY_CASK = "frely-client";
|
|
35
|
+
export declare const DARWIN_APP_NAMES: readonly ["Frely App.app", "Frely Client.app"];
|
|
36
|
+
export type AppManagerDeps = {
|
|
37
|
+
platform?: NodeJS.Platform;
|
|
38
|
+
arch?: string;
|
|
39
|
+
env?: NodeJS.ProcessEnv;
|
|
40
|
+
fetchText?: (url: string) => Promise<string>;
|
|
41
|
+
downloadFile?: (url: string, destination: string) => Promise<void>;
|
|
42
|
+
run?: (command: string, args: string[]) => Promise<{
|
|
43
|
+
code: number;
|
|
44
|
+
stdout: string;
|
|
45
|
+
stderr: string;
|
|
46
|
+
}>;
|
|
47
|
+
which?: (command: string) => string | undefined;
|
|
48
|
+
pathExists?: (path: string) => Promise<boolean>;
|
|
49
|
+
log?: (message: string) => void;
|
|
50
|
+
};
|
|
51
|
+
export declare function resolveDeps(deps?: AppManagerDeps): Required<AppManagerDeps>;
|
|
52
|
+
/** Lists published app releases on the distribution mirror, newest tags first. */
|
|
53
|
+
export declare function listAppReleases(deps?: AppManagerDeps, limit?: number): Promise<AppRelease[]>;
|
|
54
|
+
export type AssetSelection = {
|
|
55
|
+
release: AppRelease;
|
|
56
|
+
asset: AppAsset;
|
|
57
|
+
sha256Url: string | undefined;
|
|
58
|
+
};
|
|
59
|
+
/** Picks the best asset for the current platform/arch. */
|
|
60
|
+
export declare function selectAssetForPlatform(releases: AppRelease[], platform: NodeJS.Platform, arch: string): AssetSelection | null;
|
|
61
|
+
export declare function appInstallStatus(deps?: AppManagerDeps): Promise<AppInstallStatus>;
|
|
62
|
+
export type InstallResult = {
|
|
63
|
+
installed: boolean;
|
|
64
|
+
method: "homebrew" | "download";
|
|
65
|
+
path?: string;
|
|
66
|
+
version?: string;
|
|
67
|
+
};
|
|
68
|
+
export declare function installApp(deps?: AppManagerDeps, options?: {
|
|
69
|
+
force?: boolean;
|
|
70
|
+
}): Promise<InstallResult>;
|
|
71
|
+
export declare function openApp(deps?: AppManagerDeps, options?: {
|
|
72
|
+
window?: boolean;
|
|
73
|
+
}): Promise<void>;
|
|
74
|
+
export declare function updateApp(deps?: AppManagerDeps): Promise<InstallResult>;
|
|
75
|
+
export declare function uninstallApp(deps?: AppManagerDeps): Promise<void>;
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { accessSync, constants } from "node:fs";
|
|
3
|
+
import { access, mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
|
|
4
|
+
import { homedir, tmpdir } from "node:os";
|
|
5
|
+
import { delimiter, join, resolve } from "node:path";
|
|
6
|
+
export const DISTRIBUTION_REPO = "FrelyHQ/frely-cli";
|
|
7
|
+
export const TAG_PREFIXES = ["frely-app-v", "frely-client-v"];
|
|
8
|
+
export const ASSET_PREFIXES = ["Frely-App-", "Pi-Client-"];
|
|
9
|
+
export const HOMEBREW_CASK = "frely-app";
|
|
10
|
+
export const HOMEBREW_LEGACY_CASK = "frely-client";
|
|
11
|
+
export const DARWIN_APP_NAMES = ["Frely App.app", "Frely Client.app"];
|
|
12
|
+
const defaultRun = (command, args) => new Promise((resolveRun) => {
|
|
13
|
+
const child = spawn(command, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
14
|
+
let stdout = "";
|
|
15
|
+
let stderr = "";
|
|
16
|
+
child.stdout.on("data", (chunk) => (stdout += chunk.toString()));
|
|
17
|
+
child.stderr.on("data", (chunk) => (stderr += chunk.toString()));
|
|
18
|
+
child.on("error", (error) => resolveRun({ code: -1, stdout, stderr: String(error) }));
|
|
19
|
+
child.on("close", (code) => resolveRun({ code: code ?? -1, stdout, stderr }));
|
|
20
|
+
});
|
|
21
|
+
const defaultFetchText = async (url) => {
|
|
22
|
+
const response = await fetch(url, { headers: { accept: "application/vnd.github+json" } });
|
|
23
|
+
if (!response.ok)
|
|
24
|
+
throw new Error(`Request failed (${response.status}): ${url}`);
|
|
25
|
+
return response.text();
|
|
26
|
+
};
|
|
27
|
+
const defaultDownloadFile = async (url, destination) => {
|
|
28
|
+
const response = await fetch(url);
|
|
29
|
+
if (!response.ok || !response.body)
|
|
30
|
+
throw new Error(`Download failed (${response.status}): ${url}`);
|
|
31
|
+
const bytes = Buffer.from(await response.arrayBuffer());
|
|
32
|
+
await writeFile(destination, bytes);
|
|
33
|
+
};
|
|
34
|
+
export function resolveDeps(deps = {}) {
|
|
35
|
+
return {
|
|
36
|
+
platform: deps.platform ?? process.platform,
|
|
37
|
+
arch: deps.arch ?? process.arch,
|
|
38
|
+
env: deps.env ?? process.env,
|
|
39
|
+
fetchText: deps.fetchText ?? defaultFetchText,
|
|
40
|
+
downloadFile: deps.downloadFile ?? defaultDownloadFile,
|
|
41
|
+
run: deps.run ?? defaultRun,
|
|
42
|
+
which: deps.which ?? ((command) => (defaultWhich(command) ? command : undefined)),
|
|
43
|
+
pathExists: deps.pathExists ?? fileExists,
|
|
44
|
+
log: deps.log ?? ((message) => process.stdout.write(`${message}\n`)),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function defaultWhich(command) {
|
|
48
|
+
const pathDirectories = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
|
|
49
|
+
const candidates = process.platform === "win32" ? [command, `${command}.exe`] : [command];
|
|
50
|
+
for (const directory of pathDirectories) {
|
|
51
|
+
for (const candidate of candidates) {
|
|
52
|
+
try {
|
|
53
|
+
accessSync(join(directory, candidate));
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// continue
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
/** Lists published app releases on the distribution mirror, newest tags first. */
|
|
64
|
+
export async function listAppReleases(deps = {}, limit = 10) {
|
|
65
|
+
const d = resolveDeps(deps);
|
|
66
|
+
const body = await d.fetchText(`https://api.github.com/repos/${DISTRIBUTION_REPO}/releases?per_page=30`);
|
|
67
|
+
const raw = JSON.parse(body);
|
|
68
|
+
return raw
|
|
69
|
+
.filter((release) => TAG_PREFIXES.some((prefix) => release.tag_name.startsWith(prefix)))
|
|
70
|
+
.map((release) => ({
|
|
71
|
+
tag: release.tag_name,
|
|
72
|
+
version: release.tag_name.replace(/^frely-(app|client)-v/, ""),
|
|
73
|
+
prerelease: release.prerelease,
|
|
74
|
+
assets: (release.assets ?? []).map((asset) => ({ name: asset.name, url: asset.browser_download_url, size: asset.size })),
|
|
75
|
+
}))
|
|
76
|
+
.slice(0, limit);
|
|
77
|
+
}
|
|
78
|
+
/** Picks the best asset for the current platform/arch. */
|
|
79
|
+
export function selectAssetForPlatform(releases, platform, arch) {
|
|
80
|
+
const normalizedArch = arch === "x64" ? "x64" : arch;
|
|
81
|
+
const wants = platform === "darwin"
|
|
82
|
+
? ["macos", "darwin"]
|
|
83
|
+
: platform === "win32"
|
|
84
|
+
? ["windows", "win32"]
|
|
85
|
+
: ["linux"];
|
|
86
|
+
const matchAsset = (release, prefix, predicate) => {
|
|
87
|
+
const asset = release.assets.find((candidate) => {
|
|
88
|
+
const lower = candidate.name.toLowerCase();
|
|
89
|
+
return candidate.name.startsWith(prefix) && predicate(lower);
|
|
90
|
+
});
|
|
91
|
+
if (!asset)
|
|
92
|
+
return undefined;
|
|
93
|
+
const sha256 = release.assets.find((candidate) => candidate.name === `${asset.name}.sha256`);
|
|
94
|
+
return { release, asset, sha256Url: sha256 ? sha256.url : undefined };
|
|
95
|
+
};
|
|
96
|
+
const validExtensions = (lower) => lower.endsWith(".dmg") || lower.endsWith(".zip") || lower.endsWith(".appimage") || lower.endsWith(".exe");
|
|
97
|
+
const archMatchers = platform === "win32"
|
|
98
|
+
? [(lower) => lower.includes("x64")]
|
|
99
|
+
: [
|
|
100
|
+
(lower) => lower.includes(normalizedArch) || (normalizedArch === "x64" && lower.includes("amd64")),
|
|
101
|
+
(lower) => lower.includes("universal"),
|
|
102
|
+
];
|
|
103
|
+
for (const prefix of ASSET_PREFIXES) {
|
|
104
|
+
for (const release of releases) {
|
|
105
|
+
// Prefer an arch-specific asset, then fall back to universal builds.
|
|
106
|
+
for (const archMatcher of archMatchers) {
|
|
107
|
+
const selection = matchAsset(release, prefix, (lower) => validExtensions(lower) && wants.some((token) => lower.includes(token)) && archMatcher(lower));
|
|
108
|
+
if (selection)
|
|
109
|
+
return selection;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
async function fileExists(path) {
|
|
116
|
+
try {
|
|
117
|
+
await access(path, constants.F_OK);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function darwinAppDirectories(deps) {
|
|
125
|
+
const applications = resolve("/Applications");
|
|
126
|
+
const userApplications = join(homedir(), "Applications");
|
|
127
|
+
const names = deps.platform === "darwin" ? DARWIN_APP_NAMES : [];
|
|
128
|
+
const directories = [];
|
|
129
|
+
for (const base of [applications, userApplications]) {
|
|
130
|
+
for (const name of names)
|
|
131
|
+
directories.push(join(base, name));
|
|
132
|
+
}
|
|
133
|
+
return directories;
|
|
134
|
+
}
|
|
135
|
+
export async function appInstallStatus(deps = {}) {
|
|
136
|
+
const d = resolveDeps(deps);
|
|
137
|
+
if (d.platform === "darwin") {
|
|
138
|
+
const brew = d.which("brew");
|
|
139
|
+
let managedBy = "none";
|
|
140
|
+
if (brew) {
|
|
141
|
+
const info = await d.run("brew", ["list", "--cask", HOMEBREW_CASK]);
|
|
142
|
+
const legacy = info.code === 0 ? null : await d.run("brew", ["list", "--cask", HOMEBREW_LEGACY_CASK]);
|
|
143
|
+
if (info.code === 0 || legacy?.code === 0)
|
|
144
|
+
managedBy = "homebrew";
|
|
145
|
+
}
|
|
146
|
+
for (const directory of darwinAppDirectories(d)) {
|
|
147
|
+
if (await d.pathExists(directory)) {
|
|
148
|
+
const plist = join(directory, "Contents/Info.plist");
|
|
149
|
+
const version = await d
|
|
150
|
+
.run("defaults", ["read", plist, "CFBundleShortVersionString"])
|
|
151
|
+
.then((result) => (result.code === 0 ? result.stdout.trim() : undefined))
|
|
152
|
+
.catch(() => undefined);
|
|
153
|
+
const running = await d
|
|
154
|
+
.run("pgrep", ["-f", `${directory}/Contents/MacOS/`])
|
|
155
|
+
.then((result) => result.code === 0)
|
|
156
|
+
.catch(() => false);
|
|
157
|
+
return { installed: true, path: directory, ...(version ? { version } : {}), running, managedBy: managedBy === "homebrew" ? "homebrew" : "manual" };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return { installed: false, running: false, managedBy };
|
|
161
|
+
}
|
|
162
|
+
// Linux/Windows: installed state is tracked by the download destination.
|
|
163
|
+
const destination = await appDownloadDestination(d);
|
|
164
|
+
if (destination && (await d.pathExists(destination))) {
|
|
165
|
+
return { installed: true, path: destination, running: false, managedBy: "manual" };
|
|
166
|
+
}
|
|
167
|
+
return { installed: false, running: false, managedBy: "none" };
|
|
168
|
+
}
|
|
169
|
+
async function appDownloadDestination(d) {
|
|
170
|
+
if (d.platform === "linux")
|
|
171
|
+
return join(homedir(), ".local", "opt", "frely-app");
|
|
172
|
+
if (d.platform === "win32")
|
|
173
|
+
return join(d.env.LOCALAPPDATA ?? join(homedir(), "AppData", "Local"), "FrelyApp");
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
async function verifySha256(d, assetPath, sha256Url) {
|
|
177
|
+
if (!sha256Url)
|
|
178
|
+
return;
|
|
179
|
+
const checksum = (await d.fetchText(sha256Url)).trim().split(/\s+/)[0];
|
|
180
|
+
if (!checksum || !/^[0-9a-f]{64}$/.test(checksum))
|
|
181
|
+
return;
|
|
182
|
+
const { createHash } = await import("node:crypto");
|
|
183
|
+
const actual = createHash("sha256").update(await readFile(assetPath)).digest("hex");
|
|
184
|
+
if (actual !== checksum)
|
|
185
|
+
throw new Error(`SHA-256 mismatch for ${assetPath}: expected ${checksum}, got ${actual}`);
|
|
186
|
+
}
|
|
187
|
+
async function findFirstExisting(d, paths) {
|
|
188
|
+
for (const candidate of paths) {
|
|
189
|
+
if (await d.pathExists(candidate))
|
|
190
|
+
return candidate;
|
|
191
|
+
}
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
export async function installApp(deps = {}, options = {}) {
|
|
195
|
+
const d = resolveDeps(deps);
|
|
196
|
+
if (!options.force) {
|
|
197
|
+
const status = await appInstallStatus(deps);
|
|
198
|
+
if (status.installed) {
|
|
199
|
+
d.log(`Frely App is already installed${status.version ? ` (version ${status.version})` : ""} at ${status.path}.`);
|
|
200
|
+
d.log("Pass --force to reinstall or run `frely app update`.");
|
|
201
|
+
return { installed: true, method: status.managedBy === "homebrew" ? "homebrew" : "download", ...(status.path ? { path: status.path } : {}), ...(status.version ? { version: status.version } : {}) };
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (d.platform === "darwin") {
|
|
205
|
+
const brew = d.which("brew");
|
|
206
|
+
if (brew) {
|
|
207
|
+
d.log("Installing with Homebrew: brew install --cask frelyhq/tap/frely-app …");
|
|
208
|
+
const result = await d.run("brew", ["install", "--cask", `frelyhq/tap/${HOMEBREW_CASK}`]);
|
|
209
|
+
if (result.code !== 0) {
|
|
210
|
+
d.log(result.stderr || result.stdout || "brew install failed.");
|
|
211
|
+
throw new Error("brew install failed");
|
|
212
|
+
}
|
|
213
|
+
d.log("Installed. First launch: in Finder, Control-click \"Frely App\", choose Open, and confirm Open (quarantine is preserved on purpose).");
|
|
214
|
+
const status = await appInstallStatus(deps);
|
|
215
|
+
return { installed: true, method: "homebrew", ...(status.path ? { path: status.path } : {}), ...(status.version ? { version: status.version } : {}) };
|
|
216
|
+
}
|
|
217
|
+
return installFromRelease(deps, { destinationHint: resolve("/Applications") });
|
|
218
|
+
}
|
|
219
|
+
return installFromRelease(deps, {});
|
|
220
|
+
}
|
|
221
|
+
async function installFromRelease(deps, options) {
|
|
222
|
+
const d = resolveDeps(deps);
|
|
223
|
+
const releases = await listAppReleases(deps);
|
|
224
|
+
const selection = selectAssetForPlatform(releases, d.platform, d.arch);
|
|
225
|
+
if (!selection)
|
|
226
|
+
throw new Error(`No Frely App release asset found for ${d.platform}/${d.arch} on ${DISTRIBUTION_REPO} (looked for tags ${TAG_PREFIXES.join(", ")}).`);
|
|
227
|
+
d.log(`Downloading ${selection.asset.name} (${(selection.asset.size / 1_048_576).toFixed(1)} MB) from ${selection.release.tag} …`);
|
|
228
|
+
const downloadDirectory = join(tmpdir(), "frely-app-install");
|
|
229
|
+
await rm(downloadDirectory, { recursive: true, force: true });
|
|
230
|
+
await mkdir(downloadDirectory, { recursive: true });
|
|
231
|
+
const assetPath = join(downloadDirectory, selection.asset.name);
|
|
232
|
+
await d.downloadFile(selection.asset.url, assetPath);
|
|
233
|
+
await verifySha256(d, assetPath, selection.sha256Url);
|
|
234
|
+
d.log("Download verified.");
|
|
235
|
+
if (d.platform === "darwin") {
|
|
236
|
+
const target = options.destinationHint && (await directoryWritable(options.destinationHint)) ? options.destinationHint : join(homedir(), "Applications");
|
|
237
|
+
const installedPath = join(target, DARWIN_APP_NAMES[0]);
|
|
238
|
+
if (selection.asset.name.endsWith(".zip")) {
|
|
239
|
+
const extracted = join(downloadDirectory, "extracted");
|
|
240
|
+
await mkdir(extracted, { recursive: true });
|
|
241
|
+
const extract = await d.run("ditto", ["-x", "-k", assetPath, extracted]);
|
|
242
|
+
if (extract.code !== 0)
|
|
243
|
+
throw new Error(`Extraction failed: ${extract.stderr}`);
|
|
244
|
+
const appSource = await findFirstExisting(d, DARWIN_APP_NAMES.map((name) => join(extracted, name)));
|
|
245
|
+
if (!appSource)
|
|
246
|
+
throw new Error("No .app bundle found inside the downloaded archive.");
|
|
247
|
+
const copy = await d.run("ditto", [appSource, installedPath]);
|
|
248
|
+
if (copy.code !== 0)
|
|
249
|
+
throw new Error(`Copy failed: ${copy.stderr}`);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
// dmg: mount, copy, unmount — quarantine is preserved (no -no-quarantine).
|
|
253
|
+
const mountPoint = join(downloadDirectory, "mounted");
|
|
254
|
+
await mkdir(mountPoint, { recursive: true });
|
|
255
|
+
const mount = await d.run("hdiutil", ["attach", "-nobrowse", "-readonly", "-mountpoint", mountPoint, assetPath]);
|
|
256
|
+
if (mount.code !== 0)
|
|
257
|
+
throw new Error(`Could not mount ${assetPath}: ${mount.stderr}`);
|
|
258
|
+
try {
|
|
259
|
+
const appSource = await findFirstExisting(d, DARWIN_APP_NAMES.map((name) => join(mountPoint, name)));
|
|
260
|
+
if (!appSource)
|
|
261
|
+
throw new Error("No .app bundle found inside the downloaded image.");
|
|
262
|
+
const copy = await d.run("ditto", [appSource, installedPath]);
|
|
263
|
+
if (copy.code !== 0)
|
|
264
|
+
throw new Error(`Copy failed: ${copy.stderr}`);
|
|
265
|
+
}
|
|
266
|
+
finally {
|
|
267
|
+
await d.run("hdiutil", ["detach", mountPoint, "-force"]);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
d.log(`Installed to ${installedPath}.`);
|
|
271
|
+
d.log("First launch: in Finder, Control-click \"Frely App\", choose Open, and confirm Open (quarantine is preserved on purpose).");
|
|
272
|
+
return { installed: true, method: "download", path: installedPath };
|
|
273
|
+
}
|
|
274
|
+
const destination = await appDownloadDestination(d);
|
|
275
|
+
if (!destination)
|
|
276
|
+
throw new Error(`Unsupported platform for direct download: ${d.platform}`);
|
|
277
|
+
await mkdir(destination, { recursive: true });
|
|
278
|
+
const target = join(destination, selection.asset.name);
|
|
279
|
+
await d.downloadFile(selection.asset.url, target);
|
|
280
|
+
await verifySha256(d, target, selection.sha256Url);
|
|
281
|
+
if (d.platform === "linux" && target.endsWith(".AppImage")) {
|
|
282
|
+
const chmod = await d.run("chmod", ["+x", target]);
|
|
283
|
+
if (chmod.code !== 0)
|
|
284
|
+
d.log("Warning: could not mark the AppImage executable; run chmod +x manually.");
|
|
285
|
+
}
|
|
286
|
+
d.log(`Installed to ${target}.`);
|
|
287
|
+
return { installed: true, method: "download", path: target };
|
|
288
|
+
}
|
|
289
|
+
async function directoryWritable(directory) {
|
|
290
|
+
try {
|
|
291
|
+
const info = await stat(directory);
|
|
292
|
+
await access(directory, constants.W_OK);
|
|
293
|
+
return info.isDirectory();
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
export async function openApp(deps = {}, options = {}) {
|
|
300
|
+
const d = resolveDeps(deps);
|
|
301
|
+
const status = await appInstallStatus(deps);
|
|
302
|
+
if (!status.installed || !status.path)
|
|
303
|
+
throw new Error("Frely App is not installed. Run `frely app install` first.");
|
|
304
|
+
if (d.platform === "darwin") {
|
|
305
|
+
const args = options.window ? ["-a", status.path] : ["-g", "-a", status.path];
|
|
306
|
+
const result = await d.run("open", args);
|
|
307
|
+
if (result.code !== 0)
|
|
308
|
+
throw new Error(`Could not open Frely App: ${result.stderr}`);
|
|
309
|
+
d.log(options.window ? "Frely App opened." : "Frely App started in the background.");
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
if (d.platform === "linux") {
|
|
313
|
+
const result = await d.run("xdg-open", [status.path]);
|
|
314
|
+
if (result.code !== 0)
|
|
315
|
+
throw new Error(`Could not open Frely App: ${result.stderr}`);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
const result = await d.run("cmd", ["/c", "start", "", status.path]);
|
|
319
|
+
if (result.code !== 0)
|
|
320
|
+
throw new Error(`Could not open Frely App: ${result.stderr}`);
|
|
321
|
+
}
|
|
322
|
+
export async function updateApp(deps = {}) {
|
|
323
|
+
const d = resolveDeps(deps);
|
|
324
|
+
const status = await appInstallStatus(deps);
|
|
325
|
+
if (status.managedBy === "homebrew") {
|
|
326
|
+
d.log("Updating with Homebrew …");
|
|
327
|
+
const result = await d.run("brew", ["upgrade", "--cask", HOMEBREW_CASK]);
|
|
328
|
+
if (result.code !== 0)
|
|
329
|
+
throw new Error(`brew upgrade failed: ${result.stderr}`);
|
|
330
|
+
return { installed: true, method: "homebrew" };
|
|
331
|
+
}
|
|
332
|
+
if (!status.installed)
|
|
333
|
+
throw new Error("Frely App is not installed. Run `frely app install` first.");
|
|
334
|
+
return installApp(deps, { force: true });
|
|
335
|
+
}
|
|
336
|
+
export async function uninstallApp(deps = {}) {
|
|
337
|
+
const d = resolveDeps(deps);
|
|
338
|
+
const status = await appInstallStatus(deps);
|
|
339
|
+
if (!status.installed) {
|
|
340
|
+
d.log("Frely App is not installed.");
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
if (status.managedBy === "homebrew") {
|
|
344
|
+
const result = await d.run("brew", ["uninstall", "--cask", HOMEBREW_CASK]);
|
|
345
|
+
if (result.code !== 0)
|
|
346
|
+
throw new Error(`brew uninstall failed: ${result.stderr}`);
|
|
347
|
+
d.log("Uninstalled with Homebrew. User data (tasks, credentials, worktrees) stays with frely-cli.");
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
if (d.platform === "darwin" && status.path) {
|
|
351
|
+
await rm(status.path, { recursive: true, force: true });
|
|
352
|
+
d.log(`Removed ${status.path}. User data (tasks, credentials, worktrees) stays with frely-cli.`);
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
if (status.path) {
|
|
356
|
+
await rm(resolve(status.path, ".."), { recursive: true, force: true });
|
|
357
|
+
d.log(`Removed ${status.path}. User data stays with frely-cli.`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=app-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-manager.js","sourceRoot":"","sources":["../src/app-manager.ts"],"names":[],"mappings":"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"}
|