@averyyy/pi-client 0.80.3-piclient.3 → 0.80.3-piclient.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/CHANGELOG.md +6 -0
- package/README.md +4 -2
- package/bin/pi-client.js +2 -2
- package/bin/update.js +27 -1
- package/bin/web.js +37 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -5,5 +5,11 @@
|
|
|
5
5
|
- Initial `pi-client` package as a lightweight wrapper that exposes only the `pi-client` bin without `pi`.
|
|
6
6
|
- Global install wrapper that launches the local forked coding-agent entrypoint while sharing the original `~/.pi/agent` configuration.
|
|
7
7
|
- `pi-client update` command for updating the fork checkout and reinstalling both `pi-client` and `pi-server`.
|
|
8
|
+
- npm global package updates during `pi-client update`.
|
|
8
9
|
- `pi-client web` command that starts the PI WEB client GUI on port `1838` by default.
|
|
9
10
|
- Pi Server status, URL settings, client actions, project visibility, and global `AGENTS.md` editing inside `pi-client web`.
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Used `--legacy-peer-deps` for npm-global fork updates and documented installs so existing upstream Pi installs do not trigger peer override warnings for forked prerelease aliases.
|
|
15
|
+
- Fixed `pi-client web` startup on Windows by using PI WEB's TCP session daemon mode instead of the default Unix socket path.
|
package/README.md
CHANGED
|
@@ -5,9 +5,11 @@ Client CLI for connecting Pi to a `pi-server` instance.
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm i -g @averyyy/pi-client
|
|
8
|
+
npm i -g --ignore-scripts --legacy-peer-deps @averyyy/pi-client
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
`--legacy-peer-deps` avoids npm peer override warnings when upstream Pi is already installed globally.
|
|
12
|
+
|
|
11
13
|
## Use
|
|
12
14
|
|
|
13
15
|
Connect to the hosted server:
|
|
@@ -43,5 +45,5 @@ PI_SERVER_AUTH_TOKEN=your-token PI_SERVER_URL=http://127.0.0.1:4217 pi-client
|
|
|
43
45
|
Install the server separately:
|
|
44
46
|
|
|
45
47
|
```bash
|
|
46
|
-
npm i -g @averyyy/pi-server
|
|
48
|
+
npm i -g --ignore-scripts @averyyy/pi-server
|
|
47
49
|
```
|
package/bin/pi-client.js
CHANGED
|
@@ -6,8 +6,8 @@ import { fileURLToPath } from "node:url";
|
|
|
6
6
|
const args = process.argv.slice(2);
|
|
7
7
|
const modulePromise =
|
|
8
8
|
args[0] === "update"
|
|
9
|
-
? import("./update.js").then(({ runPiClientUpdate }) => {
|
|
10
|
-
process.exitCode = runPiClientUpdate(args.slice(1));
|
|
9
|
+
? import("./update.js").then(async ({ runPiClientUpdate }) => {
|
|
10
|
+
process.exitCode = await runPiClientUpdate(args.slice(1));
|
|
11
11
|
})
|
|
12
12
|
: args[0] === "web"
|
|
13
13
|
? import("./web.js").then(async ({ runPiClientWeb }) => {
|
package/bin/update.js
CHANGED
|
@@ -19,7 +19,30 @@ function runStep(runner, command, args, cwd, stdio = "inherit") {
|
|
|
19
19
|
return runner(command, args, { cwd, stdio, encoding: "utf-8" });
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
function isMissingGitCheckout(result) {
|
|
23
|
+
const text = `${String(result.stdout ?? "")}\n${String(result.stderr ?? "")}`;
|
|
24
|
+
return result.status !== 0 && text.includes("not a git repository");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function runNpmGlobalUpdate(runner, repoRoot, stdout, stderr) {
|
|
28
|
+
stdout.write("Updating npm packages: @averyyy/pi-client@latest @averyyy/pi-server@latest\n");
|
|
29
|
+
const result = runStep(
|
|
30
|
+
runner,
|
|
31
|
+
"npm",
|
|
32
|
+
["install", "-g", "--ignore-scripts", "--legacy-peer-deps", "@averyyy/pi-client@latest", "@averyyy/pi-server@latest"],
|
|
33
|
+
repoRoot,
|
|
34
|
+
);
|
|
35
|
+
if (result.status !== 0) {
|
|
36
|
+
stderr.write(
|
|
37
|
+
"pi-client update failed: npm install -g --ignore-scripts --legacy-peer-deps @averyyy/pi-client@latest @averyyy/pi-server@latest\n",
|
|
38
|
+
);
|
|
39
|
+
return result.status ?? 1;
|
|
40
|
+
}
|
|
41
|
+
stdout.write("pi-client update complete\n");
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function runPiClientUpdate(_args = [], options = {}) {
|
|
23
46
|
const packageRoot = options.packageRoot ?? defaultPackageRoot();
|
|
24
47
|
const repoRoot = options.repoRoot ?? defaultRepoRoot();
|
|
25
48
|
const runner = options.runner ?? spawnSync;
|
|
@@ -34,6 +57,9 @@ export function runPiClientUpdate(_args = [], options = {}) {
|
|
|
34
57
|
|
|
35
58
|
const status = runStep(runner, "git", ["status", "--porcelain"], repoRoot, "pipe");
|
|
36
59
|
if (status.status !== 0) {
|
|
60
|
+
if (isMissingGitCheckout(status)) {
|
|
61
|
+
return runNpmGlobalUpdate(runner, repoRoot, stdout, stderr);
|
|
62
|
+
}
|
|
37
63
|
stderr.write("pi-client update failed: unable to inspect git status\n");
|
|
38
64
|
return status.status ?? 1;
|
|
39
65
|
}
|
package/bin/web.js
CHANGED
|
@@ -3,6 +3,7 @@ import { spawn } from "node:child_process";
|
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
|
+
import { createServer } from "node:net";
|
|
6
7
|
import { homedir } from "node:os";
|
|
7
8
|
import { dirname, join } from "node:path";
|
|
8
9
|
import { fileURLToPath } from "node:url";
|
|
@@ -19,6 +20,24 @@ const binDir = dirname(fileURLToPath(import.meta.url));
|
|
|
19
20
|
const defaultPort = "1838";
|
|
20
21
|
const defaultPiServerUrl = "http://127.0.0.1:4217";
|
|
21
22
|
|
|
23
|
+
export async function piClientWebSessiondEnv(env = process.env, platform = process.platform) {
|
|
24
|
+
if (platform !== "win32") return {};
|
|
25
|
+
if (env.PI_WEB_SESSIOND_URL !== undefined && env.PI_WEB_SESSIOND_URL !== "") return {};
|
|
26
|
+
if (env.PI_WEB_SESSIOND_SOCKET !== undefined && env.PI_WEB_SESSIOND_SOCKET !== "") return {};
|
|
27
|
+
|
|
28
|
+
const host = env.PI_WEB_SESSIOND_HOST !== undefined && env.PI_WEB_SESSIOND_HOST !== "" ? env.PI_WEB_SESSIOND_HOST : "127.0.0.1";
|
|
29
|
+
const port =
|
|
30
|
+
env.PI_WEB_SESSIOND_PORT !== undefined && env.PI_WEB_SESSIOND_PORT !== ""
|
|
31
|
+
? env.PI_WEB_SESSIOND_PORT
|
|
32
|
+
: String(await findOpenTcpPort(host));
|
|
33
|
+
const urlHost = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
|
|
34
|
+
return {
|
|
35
|
+
PI_WEB_SESSIOND_HOST: host,
|
|
36
|
+
PI_WEB_SESSIOND_PORT: port,
|
|
37
|
+
PI_WEB_SESSIOND_URL: `http://${urlHost}:${port}`,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
22
41
|
export async function runPiClientWeb(args = process.argv.slice(2)) {
|
|
23
42
|
const parsed = parseArgs(args);
|
|
24
43
|
if (parsed.help) {
|
|
@@ -28,8 +47,11 @@ export async function runPiClientWeb(args = process.argv.slice(2)) {
|
|
|
28
47
|
|
|
29
48
|
process.title = "pi-client web";
|
|
30
49
|
const piServer = await effectivePiServerSettings(process.env);
|
|
50
|
+
const sessiondEnv = await piClientWebSessiondEnv(process.env);
|
|
51
|
+
Object.assign(process.env, sessiondEnv);
|
|
31
52
|
const childEnv = {
|
|
32
53
|
...process.env,
|
|
54
|
+
...sessiondEnv,
|
|
33
55
|
PI_CODING_AGENT: "true",
|
|
34
56
|
PI_SERVER_MODE: "true",
|
|
35
57
|
PI_SERVER_URL: piServer.serverUrl,
|
|
@@ -77,6 +99,21 @@ export async function runPiClientWeb(args = process.argv.slice(2)) {
|
|
|
77
99
|
});
|
|
78
100
|
}
|
|
79
101
|
|
|
102
|
+
async function findOpenTcpPort(host) {
|
|
103
|
+
return await new Promise((resolve, reject) => {
|
|
104
|
+
const server = createServer();
|
|
105
|
+
server.once("error", reject);
|
|
106
|
+
server.listen(0, host, () => {
|
|
107
|
+
const address = server.address();
|
|
108
|
+
if (address === null || typeof address === "string") {
|
|
109
|
+
server.close(() => reject(new Error("Could not reserve a session daemon TCP port")));
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
server.close(() => resolve(address.port));
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
80
117
|
function registerPiClientRoutes(app, state) {
|
|
81
118
|
app.get("/api/pi-client/pi-server", async (_request, _reply) => piServerStatus(state));
|
|
82
119
|
app.put("/api/pi-client/pi-server", async (request, reply) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@averyyy/pi-client",
|
|
3
|
-
"version": "0.80.3-piclient.
|
|
3
|
+
"version": "0.80.3-piclient.6",
|
|
4
4
|
"description": "Lightweight CLI wrapper that connects to a pi-server instance",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"piClient": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"prepublishOnly": "npm run build"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@earendil-works/pi-coding-agent": "npm:@averyyy/pi-coding-agent@0.80.3-piclient.
|
|
28
|
+
"@earendil-works/pi-coding-agent": "npm:@averyyy/pi-coding-agent@0.80.3-piclient.6",
|
|
29
29
|
"@jmfederico/pi-web": "1.202606.7"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"license": "MIT",
|
|
42
42
|
"repository": {
|
|
43
43
|
"type": "git",
|
|
44
|
-
"url": "
|
|
44
|
+
"url": "https://github.com/Averyyy/pi-client",
|
|
45
45
|
"directory": "packages/pi-client"
|
|
46
46
|
},
|
|
47
47
|
"engines": {
|