frely-cli 0.23.9 → 0.23.10
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 +49 -20
- package/README.zh-CN.md +47 -19
- package/dist/agent/local/approvals.d.ts +24 -0
- package/dist/agent/local/approvals.js +79 -0
- package/dist/agent/local/approvals.js.map +1 -0
- package/dist/agent/local/command.d.ts +10 -0
- package/dist/agent/local/command.js +292 -0
- package/dist/agent/local/command.js.map +1 -0
- package/dist/agent/local/confine.d.ts +20 -0
- package/dist/agent/local/confine.js +52 -0
- package/dist/agent/local/confine.js.map +1 -0
- package/dist/agent/local/manifest.d.ts +17 -0
- package/dist/agent/local/manifest.js +55 -0
- package/dist/agent/local/manifest.js.map +1 -0
- package/dist/agent/local/model-proxy.d.ts +18 -0
- package/dist/agent/local/model-proxy.js +111 -0
- package/dist/agent/local/model-proxy.js.map +1 -0
- package/dist/agent/local/source.d.ts +28 -0
- package/dist/agent/local/source.js +64 -0
- package/dist/agent/local/source.js.map +1 -0
- package/dist/agent/local/store.d.ts +45 -0
- package/dist/agent/local/store.js +78 -0
- package/dist/agent/local/store.js.map +1 -0
- package/dist/agent/local/supervisor.d.ts +9 -0
- package/dist/agent/local/supervisor.js +62 -0
- package/dist/agent/local/supervisor.js.map +1 -0
- package/dist/agent-help.d.ts +118 -10
- package/dist/agent-help.js +25 -6
- package/dist/agent-help.js.map +1 -1
- package/dist/index.js +35 -5
- package/dist/index.js.map +1 -1
- package/dist/provider/control.d.ts +10 -0
- package/dist/provider/control.js +19 -0
- package/dist/provider/control.js.map +1 -1
- package/dist/provider/share.js +4 -1
- package/dist/provider/share.js.map +1 -1
- package/dist/runtime/sandbox.d.ts +20 -0
- package/dist/runtime/sandbox.js +39 -1
- package/dist/runtime/sandbox.js.map +1 -1
- package/dist/share/allowance.d.ts +8 -0
- package/dist/share/allowance.js +22 -0
- package/dist/share/allowance.js.map +1 -0
- package/dist/share/control.d.ts +2 -0
- package/dist/share/control.js +14 -10
- package/dist/share/control.js.map +1 -1
- package/dist/share/service-config.d.ts +39 -0
- package/dist/share/service-config.js +85 -0
- package/dist/share/service-config.js.map +1 -0
- package/dist/share/service-control.d.ts +15 -0
- package/dist/share/service-control.js +31 -0
- package/dist/share/service-control.js.map +1 -0
- package/dist/share/service-run.d.ts +55 -0
- package/dist/share/service-run.js +285 -0
- package/dist/share/service-run.js.map +1 -0
- package/dist/share/service-state.d.ts +16 -0
- package/dist/share/service-state.js +66 -0
- package/dist/share/service-state.js.map +1 -0
- package/dist/skill/access.d.ts +2 -2
- package/dist/skill/access.js +4 -2
- package/dist/skill/access.js.map +1 -1
- package/dist/skill/cloud-item.d.ts +2 -2
- package/dist/skill/cloud-item.js.map +1 -1
- package/dist/skill/entry.d.ts +1 -1
- package/dist/skill/entry.js +1 -1
- package/dist/skill/remote-mcp.d.ts +3 -0
- package/dist/skill/remote-mcp.js +7 -1
- package/dist/skill/remote-mcp.js.map +1 -1
- package/dist/skill/router.d.ts +6 -2
- package/dist/skill/router.js +4 -4
- package/dist/skill/router.js.map +1 -1
- package/dist/uninstall.d.ts +4 -0
- package/dist/uninstall.js +14 -0
- package/dist/uninstall.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -4,48 +4,42 @@
|
|
|
4
4
|
|
|
5
5
|
[Website](https://cli.frely.cloud/) · [Docs](https://cli.frely.cloud/docs/) · [Frely](https://frely.cloud/) · [English](README.md) · [简体中文](README.zh-CN.md)
|
|
6
6
|
|
|
7
|
-
Frely CLI (`frely-cli`)
|
|
7
|
+
Frely CLI (`frely-cli`) gives agents with a shell, such as Claude Code, Codex and pi, the `frely` Skill: your agent uses your Frely account and the Store from the terminal. For web ChatGPT and Claude, and to work on another computer, it connects a computer you choose to **FrelyMCP**, so those clients can use the files, shell commands and processes in the folders you allow. The computer connects out to Frely, so you open no ports.
|
|
8
8
|
|
|
9
9
|
It is also the command line for your Frely account:
|
|
10
10
|
|
|
11
|
+
- **Agents, Prompts and Skills**: install a published Frely Agent as a local Skill, or install Prompts and Skills you bought.
|
|
11
12
|
- **Device MCP**: let remote AI clients work on this computer.
|
|
12
13
|
- **Local MCP servers**: pass MCP servers that only run on this computer (for example on `127.0.0.1`) through to remote clients.
|
|
13
|
-
- **Agents, Prompts and Skills**: install a published Frely Agent as a local Skill, or install Prompts and Skills you bought.
|
|
14
14
|
- **Local model sharing**: publish a local Ollama or OpenAI-compatible runtime as your own Frely Provider.
|
|
15
15
|
|
|
16
16
|
## Install
|
|
17
17
|
|
|
18
|
-
###
|
|
18
|
+
### Let your agent set it up
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Ask an agent that has a shell (Claude Code, Codex, pi) to install the CLI, sign in and install the Skill:
|
|
21
21
|
|
|
22
|
-
```
|
|
23
|
-
curl -fsSL https://frely.cloud/
|
|
22
|
+
```text
|
|
23
|
+
Install Frely CLI and the frely Skill on this computer. On macOS or Linux run curl -fsSL https://frely.cloud/install.sh | sh; on Windows PowerShell run curl.exe -fsSLo "$env:TEMP\frely-install.ps1" https://frely.cloud/install.ps1; powershell -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\frely-install.ps1". Ask me for my email, run frely login --email <my email>, ask me for the 6-digit code from the email, then run frely login --code <code>. Then run frely skill install --host <your host: claude-code, codex, pi or generic> and read the Skill it installs. Do not run frely mcp start until I ask for it.
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
The `frely` Skill teaches the agent to use your account and to offer FrelyMCP only when a request needs it. This path does not open this computer to remote clients; `frely mcp start` does. [More](https://cli.frely.cloud/#skill)
|
|
27
|
+
|
|
28
|
+
### Install it yourself
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
`https://frely.cloud/install.sh` and `install.ps1` only install the program, for scripts and agents that need the CLI. Node.js 22 or newer is needed only for npm.
|
|
29
31
|
|
|
30
32
|
```sh
|
|
31
33
|
# macOS / Linux
|
|
32
|
-
curl -fsSL https://frely.cloud/
|
|
34
|
+
curl -fsSL https://frely.cloud/install.sh | sh
|
|
33
35
|
```
|
|
34
36
|
|
|
35
37
|
```powershell
|
|
36
38
|
# Windows (PowerShell)
|
|
37
|
-
curl.exe -fsSLo "$env:TEMP\frely-
|
|
39
|
+
curl.exe -fsSLo "$env:TEMP\frely-install.ps1" https://frely.cloud/install.ps1; powershell -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\frely-install.ps1"
|
|
38
40
|
```
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
### Let your agent set it up
|
|
43
|
-
|
|
44
|
-
Ask an agent that has a shell (Claude Code, Codex, pi) to install the CLI, sign in with `frely login --email`, and run `frely skill install --host <host>`. The `frely` Skill teaches the agent to use your account and to offer FrelyMCP only when a request needs it. This path does not open this computer to remote clients; `frely mcp start` does.
|
|
45
|
-
|
|
46
|
-
### Install only
|
|
47
|
-
|
|
48
|
-
`https://frely.cloud/install.sh` and `install.ps1` only install the program, for scripts and agents that need the CLI. Or use npm (Node.js 22 or newer):
|
|
42
|
+
Or with npm:
|
|
49
43
|
|
|
50
44
|
```sh
|
|
51
45
|
npm install --global --ignore-scripts frely-cli@latest
|
|
@@ -53,10 +47,18 @@ npm install --global --ignore-scripts frely-cli@latest
|
|
|
53
47
|
|
|
54
48
|
The installers check the SHA-256 and download from GitHub Releases first, then npmmirror and npmjs. [More](https://cli.frely.cloud/docs/help/install-only/)
|
|
55
49
|
|
|
50
|
+
Then sign in and install the Skill for your agent host:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
frely login --email <you@example.com> # then: frely login --code <6-digit code>
|
|
54
|
+
frely skill install --host <claude-code|codex|pi|generic>
|
|
55
|
+
```
|
|
56
|
+
|
|
56
57
|
## Common commands
|
|
57
58
|
|
|
58
59
|
| Command | What it does |
|
|
59
60
|
| --- | --- |
|
|
61
|
+
| `frely skill install --host <host>` | Install the `frely` Skill for an agent host (`claude-code`, `codex`, `pi` or `generic`). |
|
|
60
62
|
| `frely mcp start` | Sign in if needed, enable Device MCP, start the service and print the MCP URL. Safe to re-run. |
|
|
61
63
|
| `frely mcp status` | Show the MCP URL, workspace, authorization expiry and service state. |
|
|
62
64
|
| `frely mcp workspace add <path>` | Share another folder. `frely mcp workspace list` shows them all. |
|
|
@@ -65,7 +67,7 @@ The installers check the SHA-256 and download from GitHub Releases first, then n
|
|
|
65
67
|
| `frely mcp remove` | Revoke access for every client and uninstall the service. |
|
|
66
68
|
| `frely doctor` | Check sign-in, installation, service and connection. `-v` for details. |
|
|
67
69
|
| `frely update` | Update to the latest version in place. |
|
|
68
|
-
| `frely login` / `frely logout` | Sign in or out of your Frely account. |
|
|
70
|
+
| `frely login` / `frely logout` | Sign in or out of your Frely account. `frely login --email <you@example.com>` then `--code <code>` signs in without a browser. |
|
|
69
71
|
| `frely sandbox proxy <url>` | Forward the command sandbox's network traffic to your own HTTP(S) proxy. Without it the CLI uses `HTTPS_PROXY` / `HTTP_PROXY` / `ALL_PROXY` and, on macOS, the system proxy. `--clear` removes it; restart the service to apply. |
|
|
70
72
|
| `frely tunnel <host>:<port>` | Inside a sandboxed command: listen on `127.0.0.1` and forward TCP connections to `host:port` through the sandbox, for database and redis clients. `--local-port N` picks the local port. |
|
|
71
73
|
| `frely uninstall` | Remove Frely from this computer (lists everything first). |
|
|
@@ -74,8 +76,34 @@ All commands and options: [command reference](https://cli.frely.cloud/docs/help/
|
|
|
74
76
|
|
|
75
77
|
## Use with FrelyMCP
|
|
76
78
|
|
|
79
|
+
Use FrelyMCP from clients with no shell, such as web ChatGPT and Claude, or to work on another computer.
|
|
80
|
+
|
|
77
81
|
FrelyMCP is one MCP address for your whole account: `https://mcp.frely.cloud/mcp`. Every computer where you ran `frely mcp start` appears behind it.
|
|
78
82
|
|
|
83
|
+
### Connect a computer with a browser
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
# macOS / Linux
|
|
87
|
+
curl -fsSL https://frely.cloud/start.sh | sh
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
```powershell
|
|
91
|
+
# Windows (PowerShell)
|
|
92
|
+
curl.exe -fsSLo "$env:TEMP\frely-start.ps1" https://frely.cloud/start.ps1; powershell -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\frely-start.ps1"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The script installs the latest `frely`, opens the browser to sign in (new accounts can register there), asks you to approve this device and prints your MCP URL. Run it again any time to update. The workspace is your home directory by default; set `FRELY_WORKSPACE=/path` to share another folder. [More](https://cli.frely.cloud/docs/help/how-do-i-install/)
|
|
96
|
+
|
|
97
|
+
### Connect a server (no browser)
|
|
98
|
+
|
|
99
|
+
Get a one-time install command on the Frely website (**My Devices → Add a computer → Create install command**), or ask ChatGPT or Claude connected to FrelyMCP to add a computer. Paste it on the server:
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
curl -fsSL https://frely.cloud/start.sh | FRELY_INSTALL_TOKEN=fit_... sh
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
It installs `frely`, signs in to your account, enables Device MCP and starts the background service. The token works once and expires after 15 minutes. On Linux, run `sudo loginctl enable-linger $USER` so the service stays online after you log out of SSH. [More](https://cli.frely.cloud/docs/help/install-on-a-server/)
|
|
106
|
+
|
|
79
107
|
1. On the computer to control, run `frely mcp start` (the install scripts above already do this).
|
|
80
108
|
2. Add the URL to your client as a remote MCP server with OAuth:
|
|
81
109
|
- ChatGPT or Claude: add a custom connector with the URL.
|
|
@@ -90,6 +118,7 @@ To check the connection, ask the client to list the top-level names in your work
|
|
|
90
118
|
|
|
91
119
|
## More features
|
|
92
120
|
|
|
121
|
+
- **Agents on this computer**: `frely agent local add <username/name>` downloads an Agent's repository into its own folder and `frely agent local start <name>` runs it inside the Frely sandbox. It can write only that folder, cannot read your SSH or cloud credentials, and never sees your Frely API key; its model calls go through a local proxy that adds the key. It can reach Frely's API and, after you approve each one once, the sites its `frely.yaml` lists. [Details](docs/agent-local.md)
|
|
93
122
|
- **Frely-hosted Agents**: `frely item install <username/name> --host claude-code` installs an Agent as a local Skill; `frely agent run <username/name>` calls it. [More](https://cli.frely.cloud/docs/help/install-agents-and-items/)
|
|
94
123
|
- **Marketplace Prompts and Skills**: `frely item install <username/name> --host claude-code` (the same command installs Agents too; add `@3` for version 3). Paid parts install only when your account holds a pass. `frely item update` lists installed items that have a newer version; it changes nothing until you run `frely item update <folder>`. [More](https://cli.frely.cloud/docs/help/install-agents-and-items/)
|
|
95
124
|
- **Local model sharing**: `frely provider share ollama` publishes a loopback model server as your personal Frely Provider. [More](https://cli.frely.cloud/docs/help/share-local-model/)
|
package/README.zh-CN.md
CHANGED
|
@@ -4,48 +4,42 @@
|
|
|
4
4
|
|
|
5
5
|
[官网](https://cli.frely.cloud/zh/) · [文档](https://cli.frely.cloud/docs/) · [Frely](https://frely.cloud/) · [English](README.md) · [简体中文](README.zh-CN.md)
|
|
6
6
|
|
|
7
|
-
Frely CLI
|
|
7
|
+
Frely CLI 为 Claude Code、Codex、pi 等有 Shell 的 Agent 安装 `frely` Skill:你的 Agent 在终端使用你的 Frely 账号和 Store。对网页版 ChatGPT 和 Claude,或要操作另一台电脑时,它把你指定的一台电脑接入 **FrelyMCP**。
|
|
8
8
|
|
|
9
9
|
它也是 Frely 账号的命令行工具:
|
|
10
10
|
|
|
11
|
+
- **Agent、Prompt 与 Skill**:把已发布的 Frely Agent 安装为本地 Skill,或安装你购买的 Prompt 和 Skill。
|
|
11
12
|
- **设备 MCP**:让远程 AI 客户端操作这台电脑。
|
|
12
13
|
- **本机 MCP 服务**:把只在这台电脑上运行的 MCP 服务(例如监听 `127.0.0.1` 的)转给远程客户端使用。
|
|
13
|
-
- **Agent、Prompt 与 Skill**:把已发布的 Frely Agent 安装为本地 Skill,或安装你购买的 Prompt 和 Skill。
|
|
14
14
|
- **本地模型共享**:把本机 Ollama 或 OpenAI 兼容运行时发布为你自己的 Frely Provider。
|
|
15
15
|
|
|
16
16
|
## 安装
|
|
17
17
|
|
|
18
|
-
###
|
|
18
|
+
### 让 Agent 帮你安装
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
让有 Shell 的 Agent(Claude Code、Codex、pi)安装 CLI、登录并安装 Skill:
|
|
21
21
|
|
|
22
|
-
```
|
|
23
|
-
curl -fsSL https://frely.cloud/
|
|
22
|
+
```text
|
|
23
|
+
在这台电脑上安装 Frely CLI 和 frely Skill。macOS 或 Linux 运行 curl -fsSL https://frely.cloud/install.sh | sh;Windows PowerShell 运行 curl.exe -fsSLo "$env:TEMP\frely-install.ps1" https://frely.cloud/install.ps1; powershell -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\frely-install.ps1"。向我询问我的邮箱,运行 frely login --email <my email>,再向我要邮件里的 6 位验证码,然后运行 frely login --code <code>。接着运行 frely skill install --host <your host: claude-code, codex, pi or generic>,并阅读它安装的 Skill。在我要求之前,不要运行 frely mcp start。
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
安装的 `frely` Skill 会教 Agent 使用你的账号,只在需要时才建议 FrelyMCP。这种方式不会把这台电脑开放给远程客户端,`frely mcp start` 才会。[详情](https://cli.frely.cloud/zh/#skill)
|
|
27
|
+
|
|
28
|
+
### 自己安装
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
`https://frely.cloud/install.sh` 和 `install.ps1` 只安装程序,供脚本和 Agent 使用。也可以用 npm(需要 Node.js 22 或更新版本):
|
|
29
31
|
|
|
30
32
|
```sh
|
|
31
33
|
# macOS / Linux
|
|
32
|
-
curl -fsSL https://frely.cloud/
|
|
34
|
+
curl -fsSL https://frely.cloud/install.sh | sh
|
|
33
35
|
```
|
|
34
36
|
|
|
35
37
|
```powershell
|
|
36
38
|
# Windows(PowerShell)
|
|
37
|
-
curl.exe -fsSLo "$env:TEMP\frely-
|
|
39
|
+
curl.exe -fsSLo "$env:TEMP\frely-install.ps1" https://frely.cloud/install.ps1; powershell -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\frely-install.ps1"
|
|
38
40
|
```
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
### 让 Agent 帮你安装
|
|
43
|
-
|
|
44
|
-
让有 Shell 的 Agent(Claude Code、Codex、pi)安装 CLI,用 `frely login --email` 登录,再运行 `frely skill install --host <host>`。安装的 `frely` Skill 会教 Agent 使用你的账号,只在需要时才建议 FrelyMCP。这种方式不会把这台电脑开放给远程客户端,`frely mcp start` 才会。
|
|
45
|
-
|
|
46
|
-
### 只安装
|
|
47
|
-
|
|
48
|
-
`https://frely.cloud/install.sh` 和 `install.ps1` 只安装程序,供脚本和 Agent 使用。也可以用 npm(需要 Node.js 22 或更新版本):
|
|
42
|
+
或用 npm:
|
|
49
43
|
|
|
50
44
|
```sh
|
|
51
45
|
npm install --global --ignore-scripts frely-cli@latest
|
|
@@ -53,10 +47,18 @@ npm install --global --ignore-scripts frely-cli@latest
|
|
|
53
47
|
|
|
54
48
|
安装器会校验 SHA-256,下载先走 GitHub Releases,再回退到 npmmirror 和 npmjs。[详情](https://cli.frely.cloud/docs/help/install-only/)
|
|
55
49
|
|
|
50
|
+
然后登录并为你的 Agent 宿主安装 Skill:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
frely login --email <you@example.com> # 再运行:frely login --code <6 位验证码>
|
|
54
|
+
frely skill install --host <claude-code|codex|pi|generic>
|
|
55
|
+
```
|
|
56
|
+
|
|
56
57
|
## 常用命令
|
|
57
58
|
|
|
58
59
|
| 命令 | 作用 |
|
|
59
60
|
| --- | --- |
|
|
61
|
+
| `frely skill install --host <host>` | 为 Agent 宿主(`claude-code`、`codex`、`pi` 或 `generic`)安装 `frely` Skill。 |
|
|
60
62
|
| `frely mcp start` | 需要时登录,开启设备 MCP,启动服务并输出 MCP URL。可重复运行。 |
|
|
61
63
|
| `frely mcp status` | 显示 MCP URL、工作区、授权到期时间和服务状态。 |
|
|
62
64
|
| `frely mcp workspace add <path>` | 共享另一个文件夹。`frely mcp workspace list` 列出全部。 |
|
|
@@ -73,8 +75,34 @@ npm install --global --ignore-scripts frely-cli@latest
|
|
|
73
75
|
|
|
74
76
|
## 与 FrelyMCP 配合使用
|
|
75
77
|
|
|
78
|
+
通过 FrelyMCP,让网页版 ChatGPT、Claude 等没有 Shell 的客户端使用 Frely,或操作另一台电脑。
|
|
79
|
+
|
|
76
80
|
FrelyMCP 是整个账号共用的一个 MCP 地址:`https://mcp.frely.cloud/mcp`。每台运行过 `frely mcp start` 的电脑都在它后面。
|
|
77
81
|
|
|
82
|
+
### 连接有浏览器的电脑
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
# macOS / Linux
|
|
86
|
+
curl -fsSL https://frely.cloud/start.sh | sh
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```powershell
|
|
90
|
+
# Windows(PowerShell)
|
|
91
|
+
curl.exe -fsSLo "$env:TEMP\frely-start.ps1" https://frely.cloud/start.ps1; powershell -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\frely-start.ps1"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
脚本安装最新版 `frely`,打开浏览器登录(新账号可在同一页面注册),请你批准这台设备,最后输出 MCP URL。随时可以再运行一次来升级。工作区默认是用户主目录,设置 `FRELY_WORKSPACE=/path` 可共享其他文件夹。[详情](https://cli.frely.cloud/docs/help/how-do-i-install/)
|
|
95
|
+
|
|
96
|
+
### 连接服务器(无需浏览器)
|
|
97
|
+
|
|
98
|
+
在 Frely 网站 **My Devices → Add a computer → Create install command** 获取一次性安装命令,或让已连接 FrelyMCP 的 ChatGPT、Claude 添加一台电脑。粘贴到服务器上运行:
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
curl -fsSL https://frely.cloud/start.sh | FRELY_INSTALL_TOKEN=fit_... sh
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
它会安装 `frely`、登录你的账号、开启设备 MCP 并启动后台服务。令牌只能用一次,15 分钟内有效。Linux 上请运行 `sudo loginctl enable-linger $USER`,退出 SSH 后服务才能保持在线。[详情](https://cli.frely.cloud/docs/help/install-on-a-server/)
|
|
105
|
+
|
|
78
106
|
1. 在要被控制的电脑上运行 `frely mcp start`(上面的安装脚本已经包含这一步)。
|
|
79
107
|
2. 把 URL 作为使用 OAuth 的远程 MCP 服务加到客户端:
|
|
80
108
|
- ChatGPT 或 Claude:用这个 URL 添加自定义连接器。
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type Controller } from "../../controller/client.js";
|
|
2
|
+
import { type LocalAgentRecord } from "./store.js";
|
|
3
|
+
/** The shape of FrelyMCP's request_permission / permission_status answers that this file reads. */
|
|
4
|
+
export interface ApprovalIo {
|
|
5
|
+
err(text: string): void;
|
|
6
|
+
/** A person is at the terminal and can be waited for. */
|
|
7
|
+
interactive: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ApprovalDeps {
|
|
10
|
+
open?: () => Promise<Controller>;
|
|
11
|
+
deviceId?: () => Promise<string>;
|
|
12
|
+
now?: () => number;
|
|
13
|
+
sleep?: (ms: number) => Promise<void>;
|
|
14
|
+
pollMs?: number;
|
|
15
|
+
waitMs?: number;
|
|
16
|
+
}
|
|
17
|
+
/** The FrelyMCP resource name for one site. The relay shows it to the owner as "connect to <site>". */
|
|
18
|
+
export declare const siteResource: (host: string) => string;
|
|
19
|
+
/**
|
|
20
|
+
* Makes sure every site the Agent listed in frely.yaml is approved, asking the owner through the same approval link as any other
|
|
21
|
+
* device permission. Returns the approvals gained (site -> end time). A site the owner declines is left out and the Agent starts without it.
|
|
22
|
+
* Without a person at the terminal a pending request ends the command with exit code 3 and the link; run the command again after approving.
|
|
23
|
+
*/
|
|
24
|
+
export declare function approveSites(record: LocalAgentRecord, io: ApprovalIo, deps?: ApprovalDeps): Promise<Record<string, string>>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { ensureDevice } from "../../device/control.js";
|
|
2
|
+
import { openController, resultData, resultText } from "../../controller/client.js";
|
|
3
|
+
import { ControllerError, EXIT } from "../../controller/session.js";
|
|
4
|
+
import { approvedHosts } from "./store.js";
|
|
5
|
+
const sleepFor = (ms) => new Promise((done) => setTimeout(done, ms));
|
|
6
|
+
/** When the relay does not say, an approval is taken to last as long as its default window. */
|
|
7
|
+
const DEFAULT_WINDOW_MS = 12 * 3_600_000;
|
|
8
|
+
/** The FrelyMCP resource name for one site. The relay shows it to the owner as "connect to <site>". */
|
|
9
|
+
export const siteResource = (host) => `net:${host}`;
|
|
10
|
+
/**
|
|
11
|
+
* Makes sure every site the Agent listed in frely.yaml is approved, asking the owner through the same approval link as any other
|
|
12
|
+
* device permission. Returns the approvals gained (site -> end time). A site the owner declines is left out and the Agent starts without it.
|
|
13
|
+
* Without a person at the terminal a pending request ends the command with exit code 3 and the link; run the command again after approving.
|
|
14
|
+
*/
|
|
15
|
+
export async function approveSites(record, io, deps = {}) {
|
|
16
|
+
const now = deps.now ?? Date.now;
|
|
17
|
+
const open = deps.open ?? (() => openController({ interactive: io.interactive }));
|
|
18
|
+
const missing = record.network.filter((host) => !approvedHosts(record, now()).includes(host));
|
|
19
|
+
const gained = {};
|
|
20
|
+
if (missing.length === 0)
|
|
21
|
+
return gained;
|
|
22
|
+
const controller = await open();
|
|
23
|
+
try {
|
|
24
|
+
const device = await (deps.deviceId ?? (async () => (await ensureDevice()).deviceId))();
|
|
25
|
+
for (const host of missing) {
|
|
26
|
+
const end = await approveSite(controller, device, record, host, io, deps);
|
|
27
|
+
if (end)
|
|
28
|
+
gained[host] = end;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
await controller.close().catch(() => undefined);
|
|
33
|
+
}
|
|
34
|
+
return gained;
|
|
35
|
+
}
|
|
36
|
+
async function approveSite(controller, device, record, host, io, deps) {
|
|
37
|
+
const now = deps.now ?? Date.now;
|
|
38
|
+
const sleep = deps.sleep ?? sleepFor;
|
|
39
|
+
const result = await controller.call("request_permission", {
|
|
40
|
+
device, resource: siteResource(host), mode: "window",
|
|
41
|
+
reason: `The local Agent ${record.slug} lists ${host} in its frely.yaml.`.slice(0, 300),
|
|
42
|
+
command: `frely agent local start ${record.slug}`,
|
|
43
|
+
});
|
|
44
|
+
const data = resultData(result);
|
|
45
|
+
if (result.isError === true || !data)
|
|
46
|
+
throw new ControllerError(`Could not ask for approval of ${host}: ${resultText(result) || "no answer"}`, EXIT.tool);
|
|
47
|
+
const status = data.status;
|
|
48
|
+
if (status === "allowed")
|
|
49
|
+
return typeof data.expiresAt === "string" ? data.expiresAt : new Date(now() + DEFAULT_WINDOW_MS).toISOString();
|
|
50
|
+
if (status === "not_needed")
|
|
51
|
+
return new Date(now() + DEFAULT_WINDOW_MS).toISOString();
|
|
52
|
+
const code = typeof data.shortCode === "string" ? data.shortCode : undefined;
|
|
53
|
+
const link = typeof data.approveUrl === "string" ? data.approveUrl : undefined;
|
|
54
|
+
if (status !== "pending" || !code)
|
|
55
|
+
throw new ControllerError(`Could not ask for approval of ${host}: ${resultText(result) || String(status)}`, EXIT.tool);
|
|
56
|
+
io.err(`${record.slug} wants to connect to ${host}. Approve it here (you choose how long): ${link ?? "Frely > Device MCP"}\n`);
|
|
57
|
+
if (!io.interactive) {
|
|
58
|
+
throw new ControllerError(`Approval needed for ${host}. Open the link above, approve it, then run the same command again.`, EXIT.approval);
|
|
59
|
+
}
|
|
60
|
+
io.err("Waiting for your decision…\n");
|
|
61
|
+
const deadline = now() + (deps.waitMs ?? 10 * 60_000);
|
|
62
|
+
for (;;) {
|
|
63
|
+
const answer = resultData(await controller.call("permission_status", { code }));
|
|
64
|
+
if (answer?.status === "approved")
|
|
65
|
+
return typeof answer.expiresAt === "string" ? answer.expiresAt : new Date(now() + DEFAULT_WINDOW_MS).toISOString();
|
|
66
|
+
if (answer?.status === "denied") {
|
|
67
|
+
io.err(`${host} was declined; ${record.slug} will run without it.\n`);
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
if (answer?.status === "expired" || answer?.status === "revoked") {
|
|
71
|
+
io.err(`The request for ${host} ended without an answer; ${record.slug} will run without it.\n`);
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
if (now() + (deps.pollMs ?? 3000) >= deadline)
|
|
75
|
+
throw new ControllerError(`Still waiting for approval of ${host}. Run the same command again to keep waiting.`, EXIT.approval);
|
|
76
|
+
await sleep(deps.pollMs ?? 3000);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=approvals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../../src/agent/local/approvals.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ApprovalDeps } from "./approvals.js";
|
|
2
|
+
export interface LocalIo {
|
|
3
|
+
out(text: string): void;
|
|
4
|
+
err(text: string): void;
|
|
5
|
+
interactive: boolean;
|
|
6
|
+
readSecret(): Promise<string>;
|
|
7
|
+
}
|
|
8
|
+
export declare const LOCAL_USAGE = "Usage:\n frely agent local add <username/name | https://github.com/owner/repo> [--name <folder-name>]\n frely agent local start <name> [--foreground]\n frely agent local stop <name>\n frely agent local logs <name> [--lines <n>] [--follow]\n frely agent local list [--json]\n frely agent local remove <name>\n frely agent local key --api-key-stdin | --clear\n";
|
|
9
|
+
/** Runs `frely agent local ...`; returns the exit code. */
|
|
10
|
+
export declare function runAgentLocal(args: readonly string[], io: LocalIo, deps?: ApprovalDeps): Promise<number>;
|