@averyyy/pi-client 0.80.3-piclient.5 → 0.80.3

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 CHANGED
@@ -5,6 +5,5 @@
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 and proxy warning acknowledgement during `pi-client update`.
9
8
  - `pi-client web` command that starts the PI WEB client GUI on port `1838` by default.
10
9
  - Pi Server status, URL settings, client actions, project visibility, and global `AGENTS.md` editing inside `pi-client web`.
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(async ({ runPiClientUpdate }) => {
10
- process.exitCode = await runPiClientUpdate(args.slice(1));
9
+ ? import("./update.js").then(({ runPiClientUpdate }) => {
10
+ process.exitCode = runPiClientUpdate(args.slice(1));
11
11
  })
12
12
  : args[0] === "web"
13
13
  ? import("./web.js").then(async ({ runPiClientWeb }) => {
package/bin/update.js CHANGED
@@ -1,19 +1,8 @@
1
1
  import { spawnSync } from "node:child_process";
2
- import { Buffer } from "node:buffer";
3
2
  import { readFileSync } from "node:fs";
4
3
  import { dirname, resolve } from "node:path";
5
4
  import { fileURLToPath } from "node:url";
6
5
 
7
- const H_PROXY_WARNING_URL_PATTERN =
8
- /https?:\/\/114\.114\.114\.114:\d+\/proxycontrolwarn\/httpwarning_\d+\.html\?ori_url=[A-Za-z0-9+/=]+(?:&uid=\d+)?/;
9
- const H_PROXY_WARNING_HOST = "114.114.114.114:9421";
10
- const H_PROXY_HEADERS = {
11
- "User-Agent":
12
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121 Safari/537.36",
13
- Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
14
- "Accept-Language": "en-US,en;q=0.5",
15
- };
16
-
17
6
  function defaultPackageRoot() {
18
7
  return dirname(dirname(fileURLToPath(import.meta.url)));
19
8
  }
@@ -30,184 +19,10 @@ function runStep(runner, command, args, cwd, stdio = "inherit") {
30
19
  return runner(command, args, { cwd, stdio, encoding: "utf-8" });
31
20
  }
32
21
 
33
- function responseStatus(response) {
34
- return response.statusText ? `${response.status} ${response.statusText}` : String(response.status);
35
- }
36
-
37
- function getQueryValue(url, name) {
38
- const match = new RegExp(`[?&]${name}=([^&]+)`).exec(url);
39
- return match?.[1] ?? "";
40
- }
41
-
42
- function getInputValue(html, id) {
43
- const match = new RegExp(`id="${id}"[^>]*value="([^"]*)"`).exec(html);
44
- return match?.[1] ?? "";
45
- }
46
-
47
- function bitReverse(value) {
48
- return (
49
- ((1 & value) << 7) |
50
- ((2 & value) << 5) |
51
- ((4 & value) << 3) |
52
- ((8 & value) << 1) |
53
- ((16 & value) >> 1) |
54
- ((32 & value) >> 3) |
55
- ((64 & value) >> 5) |
56
- ((128 & value) >> 7)
57
- );
58
- }
59
-
60
- function encodeWarningByte(value) {
61
- if (value === 32) return "+";
62
- if (
63
- (value < 48 && value !== 45 && value !== 46) ||
64
- (value < 65 && value > 57) ||
65
- (value > 90 && value < 97 && value !== 95) ||
66
- value > 122
67
- ) {
68
- return `%${value.toString(16).toUpperCase().padStart(2, "0")}`;
69
- }
70
- return String.fromCharCode(value);
71
- }
72
-
73
- function md6(value) {
74
- let result = "";
75
- for (let index = 0; index < value.length; index++) {
76
- result += encodeWarningByte(53 ^ bitReverse(value.charCodeAt(index)) ^ (255 & index));
77
- }
78
- return result;
79
- }
80
-
81
- function b64(value) {
82
- return Buffer.from(value, "utf-8").toString("base64");
83
- }
84
-
85
- async function findHProxyWarningUrl(response) {
86
- const location = response.headers.get("location") ?? "";
87
- if (response.status === 302 && H_PROXY_WARNING_URL_PATTERN.test(location)) return location;
88
- if (H_PROXY_WARNING_URL_PATTERN.test(response.url)) return response.url;
89
-
90
- const contentType = response.headers.get("content-type")?.toLowerCase() ?? "";
91
- if (!contentType.includes("text/html")) return undefined;
92
-
93
- const body = await response.clone().text();
94
- return H_PROXY_WARNING_URL_PATTERN.exec(body)?.[0];
95
- }
96
-
97
- async function approveHProxyWarning(warningUrl, fetchImpl) {
98
- const warningResponse = await fetchImpl(warningUrl, {
99
- method: "GET",
100
- headers: H_PROXY_HEADERS,
101
- redirect: "manual",
102
- });
103
- const html = await warningResponse.text();
104
- if (!warningResponse.ok) {
105
- throw new Error(`Proxy warning page fetch failed: ${responseStatus(warningResponse)}`);
106
- }
107
-
108
- const oriUrl = getQueryValue(warningUrl, "ori_url");
109
- const sessionId = getInputValue(html, "sessionid");
110
- if (!oriUrl || !sessionId) {
111
- throw new Error("Proxy warning page did not include approval fields");
112
- }
113
-
114
- const pid = getInputValue(html, "pid");
115
- const uid = getInputValue(html, "uid");
116
- const payload = `ori_url=${oriUrl}&sessionid=${sessionId}&pid=${pid}&uid=${uid}`;
117
- const checkUrl = `http://${H_PROXY_WARNING_HOST}/proxycontrolwarn/check?${b64(md6(b64(payload)))}`;
118
- const checkResponse = await fetchImpl(checkUrl, {
119
- method: "GET",
120
- headers: H_PROXY_HEADERS,
121
- redirect: "manual",
122
- });
123
- const checkBody = await checkResponse.text();
124
- if (!checkResponse.ok) {
125
- throw new Error(`Proxy approval failed: ${responseStatus(checkResponse)} ${checkBody.slice(0, 80)}`);
126
- }
127
- }
128
-
129
- async function approveHProxyTarget(url, fetchImpl) {
130
- let response;
131
- try {
132
- response = await fetchImpl(url, { method: "GET", headers: H_PROXY_HEADERS, redirect: "manual" });
133
- } catch {
134
- return false;
135
- }
136
-
137
- const warningUrl = await findHProxyWarningUrl(response);
138
- if (!warningUrl) return false;
139
-
140
- await approveHProxyWarning(warningUrl, fetchImpl);
141
- return true;
142
- }
143
-
144
- function maybeGitHttpUrl(value) {
145
- const trimmed = value.trim();
146
- if (trimmed.startsWith("http://") || trimmed.startsWith("https://")) return trimmed;
147
- const ssh = /^git@([^:]+):(.+)$/.exec(trimmed);
148
- if (ssh) return `https://${ssh[1]}/${ssh[2]}`;
149
- return undefined;
150
- }
151
-
152
- function maybeHttpUrl(value) {
153
- const trimmed = value.trim();
154
- return trimmed.startsWith("http://") || trimmed.startsWith("https://") ? trimmed : undefined;
155
- }
156
-
157
- function getProxyApprovalTargets(runner, repoRoot, includeGitRemote = true) {
158
- const targets = [];
159
- if (includeGitRemote) {
160
- const remote = runStep(runner, "git", ["config", "--get", "remote.origin.url"], repoRoot, "pipe");
161
- if (remote.status === 0) {
162
- const url = maybeGitHttpUrl(String(remote.stdout ?? ""));
163
- if (url) targets.push(url);
164
- }
165
- }
166
-
167
- const registry = runStep(runner, "npm", ["config", "get", "registry"], repoRoot, "pipe");
168
- if (registry.status === 0) {
169
- const url = maybeHttpUrl(String(registry.stdout ?? ""));
170
- if (url) targets.push(url);
171
- }
172
-
173
- return [...new Set(targets)];
174
- }
175
-
176
- async function approveUpdateProxyTargets(runner, repoRoot, stdout, fetchImpl, includeGitRemote = true) {
177
- for (const target of getProxyApprovalTargets(runner, repoRoot, includeGitRemote)) {
178
- if (await approveHProxyTarget(target, fetchImpl)) {
179
- stdout.write(`Approved proxy warning for ${target}\n`);
180
- }
181
- }
182
- }
183
-
184
- function isMissingGitCheckout(result) {
185
- const text = `${String(result.stdout ?? "")}\n${String(result.stderr ?? "")}`;
186
- return result.status !== 0 && text.includes("not a git repository");
187
- }
188
-
189
- async function runNpmGlobalUpdate(runner, repoRoot, stdout, stderr, fetchImpl) {
190
- await approveUpdateProxyTargets(runner, repoRoot, stdout, fetchImpl, false);
191
- stdout.write("Updating npm packages: @averyyy/pi-client@latest @averyyy/pi-server@latest\n");
192
- const result = runStep(
193
- runner,
194
- "npm",
195
- ["install", "-g", "--ignore-scripts", "@averyyy/pi-client@latest", "@averyyy/pi-server@latest"],
196
- repoRoot,
197
- );
198
- if (result.status !== 0) {
199
- stderr.write("pi-client update failed: npm install -g --ignore-scripts @averyyy/pi-client@latest @averyyy/pi-server@latest\n");
200
- return result.status ?? 1;
201
- }
202
- stdout.write("pi-client update complete\n");
203
- return 0;
204
- }
205
-
206
- export async function runPiClientUpdate(_args = [], options = {}) {
22
+ export function runPiClientUpdate(_args = [], options = {}) {
207
23
  const packageRoot = options.packageRoot ?? defaultPackageRoot();
208
24
  const repoRoot = options.repoRoot ?? defaultRepoRoot();
209
25
  const runner = options.runner ?? spawnSync;
210
- const fetchImpl = options.fetch ?? globalThis.fetch;
211
26
  const stdout = options.stdout ?? process.stdout;
212
27
  const stderr = options.stderr ?? process.stderr;
213
28
  const pkg = readPackageMetadata(packageRoot);
@@ -219,9 +34,6 @@ export async function runPiClientUpdate(_args = [], options = {}) {
219
34
 
220
35
  const status = runStep(runner, "git", ["status", "--porcelain"], repoRoot, "pipe");
221
36
  if (status.status !== 0) {
222
- if (isMissingGitCheckout(status)) {
223
- return runNpmGlobalUpdate(runner, repoRoot, stdout, stderr, fetchImpl);
224
- }
225
37
  stderr.write("pi-client update failed: unable to inspect git status\n");
226
38
  return status.status ?? 1;
227
39
  }
@@ -230,8 +42,6 @@ export async function runPiClientUpdate(_args = [], options = {}) {
230
42
  return 1;
231
43
  }
232
44
 
233
- await approveUpdateProxyTargets(runner, repoRoot, stdout, fetchImpl);
234
-
235
45
  const steps = [
236
46
  ["git", ["pull", "--ff-only"]],
237
47
  ["npm", ["install", "--ignore-scripts"]],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@averyyy/pi-client",
3
- "version": "0.80.3-piclient.5",
3
+ "version": "0.80.3",
4
4
  "description": "Lightweight CLI wrapper that connects to a pi-server instance",
5
5
  "type": "module",
6
6
  "piClient": {
@@ -15,7 +15,6 @@
15
15
  },
16
16
  "files": [
17
17
  "bin",
18
- "README.md",
19
18
  "CHANGELOG.md"
20
19
  ],
21
20
  "scripts": {
@@ -25,7 +24,7 @@
25
24
  "prepublishOnly": "npm run build"
26
25
  },
27
26
  "dependencies": {
28
- "@earendil-works/pi-coding-agent": "npm:@averyyy/pi-coding-agent@0.80.3-piclient.5",
27
+ "@earendil-works/pi-coding-agent": "0.80.3",
29
28
  "@jmfederico/pi-web": "1.202606.7"
30
29
  },
31
30
  "devDependencies": {
@@ -41,7 +40,7 @@
41
40
  "license": "MIT",
42
41
  "repository": {
43
42
  "type": "git",
44
- "url": "https://github.com/Averyyy/pi-client",
43
+ "url": "git+https://github.com/earendil-works/pi.git",
45
44
  "directory": "packages/pi-client"
46
45
  },
47
46
  "engines": {
package/README.md DELETED
@@ -1,47 +0,0 @@
1
- # @averyyy/pi-client
2
-
3
- Client CLI for connecting Pi to a `pi-server` instance.
4
-
5
- ## Install
6
-
7
- ```bash
8
- npm i -g @averyyy/pi-client
9
- ```
10
-
11
- ## Use
12
-
13
- Connect to the hosted server:
14
-
15
- ```bash
16
- PI_SERVER_URL=https://pi.yreva.asia pi-client
17
- ```
18
-
19
- Send one prompt and exit:
20
-
21
- ```bash
22
- PI_SERVER_URL=https://pi.yreva.asia pi-client -p "Say exactly: ok"
23
- ```
24
-
25
- Start the browser UI:
26
-
27
- ```bash
28
- PI_SERVER_URL=https://pi.yreva.asia pi-client web
29
- ```
30
-
31
- The web UI listens on `http://127.0.0.1:1838` by default.
32
-
33
- ## Server Auth
34
-
35
- If your server uses an auth token, set it on the client:
36
-
37
- ```bash
38
- PI_SERVER_AUTH_TOKEN=your-token PI_SERVER_URL=http://127.0.0.1:4217 pi-client
39
- ```
40
-
41
- ## Related Package
42
-
43
- Install the server separately:
44
-
45
- ```bash
46
- npm i -g @averyyy/pi-server
47
- ```