pi-forge 1.1.6 → 1.2.0
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 +23 -13
- package/bin/pi-forge.mjs +34 -5
- package/dist/client/assets/{CodeMirrorEditor-C_ITRoQa.js → CodeMirrorEditor-DXdXoCjw.js} +2 -2
- package/dist/client/assets/{CodeMirrorEditor-C_ITRoQa.js.map → CodeMirrorEditor-DXdXoCjw.js.map} +1 -1
- package/dist/client/assets/{index-B67tDt4n.js → index-DRa0fybV.js} +69 -69
- package/dist/client/assets/index-DRa0fybV.js.map +1 -0
- package/dist/client/assets/index-b30wYoh-.css +1 -0
- package/dist/client/index.html +14 -3
- package/dist/client/manifest.webmanifest +1 -1
- package/dist/client/sw.js +1 -1
- package/dist/client/sw.js.map +1 -1
- package/dist/server/cli.js +512 -0
- package/dist/server/cli.js.map +1 -0
- package/dist/server/config.js +29 -14
- package/dist/server/config.js.map +1 -1
- package/package.json +2 -2
- package/dist/client/assets/index-B67tDt4n.js.map +0 -1
- package/dist/client/assets/index-BB-19PiX.css +0 -1
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pi-forge CLI argument parser.
|
|
3
|
+
*
|
|
4
|
+
* Pure module — does NOT import from `./config.js` or any other server
|
|
5
|
+
* module so it can run in the bin shim BEFORE the server module loads.
|
|
6
|
+
* Config reads `process.env` at import time, so flag → env writes must
|
|
7
|
+
* happen before that import.
|
|
8
|
+
*
|
|
9
|
+
* Single source of truth: the `FLAGS` table below drives:
|
|
10
|
+
* 1. argument parsing (via Node's built-in `node:util` parseArgs)
|
|
11
|
+
* 2. process.env mutation (each flag maps to its env-var equivalent)
|
|
12
|
+
* 3. `--help` rendering
|
|
13
|
+
*
|
|
14
|
+
* Adding a new env var → add one row here. Don't fork the table.
|
|
15
|
+
*
|
|
16
|
+
* Conventions:
|
|
17
|
+
* - Flag names: kebab-case, long-form only (no single-char shortcuts).
|
|
18
|
+
* - Boolean flags: `--foo true|false|on|off|1|0|yes|no`. Bare `--foo`
|
|
19
|
+
* is treated as `--foo=true`. `--no-foo` is treated as `--foo=false`.
|
|
20
|
+
* - Path flags: passed through verbatim (config.ts resolves them).
|
|
21
|
+
* - Sensitive flags (auth secrets): support `@<path>` syntax so the
|
|
22
|
+
* value can come from a file instead of argv (avoids shell history
|
|
23
|
+
* / `ps` exposure). Same convention `curl` and `gh` use.
|
|
24
|
+
* - Flag values always WIN over env. `pi-forge --port 4000` overrides
|
|
25
|
+
* `PORT=3000` in the environment. Env is a fallback — if the flag
|
|
26
|
+
* is absent, the existing env value persists, and config.ts handles
|
|
27
|
+
* the default.
|
|
28
|
+
*/
|
|
29
|
+
import { readFileSync } from "node:fs";
|
|
30
|
+
import { parseArgs } from "node:util";
|
|
31
|
+
const FLAGS = [
|
|
32
|
+
// network
|
|
33
|
+
{
|
|
34
|
+
name: "port",
|
|
35
|
+
env: "PORT",
|
|
36
|
+
type: "number",
|
|
37
|
+
group: "network",
|
|
38
|
+
desc: "HTTP listen port",
|
|
39
|
+
defaultText: "3000",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "host",
|
|
43
|
+
env: "HOST",
|
|
44
|
+
type: "string",
|
|
45
|
+
group: "network",
|
|
46
|
+
desc: "Bind address (loopback by default; set 0.0.0.0 to expose to the network)",
|
|
47
|
+
defaultText: "127.0.0.1",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: "cors-origin",
|
|
51
|
+
env: "CORS_ORIGIN",
|
|
52
|
+
type: "string",
|
|
53
|
+
group: "network",
|
|
54
|
+
desc: "CORS allow-origin (production only; dev is wide-open)",
|
|
55
|
+
defaultText: "(unset)",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "trust-proxy",
|
|
59
|
+
env: "TRUST_PROXY",
|
|
60
|
+
type: "boolean",
|
|
61
|
+
group: "network",
|
|
62
|
+
desc: "Trust X-Forwarded-* headers (set when behind a reverse proxy)",
|
|
63
|
+
defaultText: "false",
|
|
64
|
+
},
|
|
65
|
+
// paths
|
|
66
|
+
{
|
|
67
|
+
name: "workspace-path",
|
|
68
|
+
env: "WORKSPACE_PATH",
|
|
69
|
+
type: "string",
|
|
70
|
+
group: "paths",
|
|
71
|
+
desc: "Where project code lives",
|
|
72
|
+
defaultText: "~/.pi-forge/workspace",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "pi-config-dir",
|
|
76
|
+
env: "PI_CONFIG_DIR",
|
|
77
|
+
type: "string",
|
|
78
|
+
group: "paths",
|
|
79
|
+
desc: "Pi SDK config dir (auth/models/settings)",
|
|
80
|
+
defaultText: "~/.pi/agent",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "forge-data-dir",
|
|
84
|
+
env: "FORGE_DATA_DIR",
|
|
85
|
+
type: "string",
|
|
86
|
+
group: "paths",
|
|
87
|
+
desc: "Forge state dir (projects.json, mcp.json, overrides)",
|
|
88
|
+
defaultText: "~/.pi-forge",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: "session-dir",
|
|
92
|
+
env: "SESSION_DIR",
|
|
93
|
+
type: "string",
|
|
94
|
+
group: "paths",
|
|
95
|
+
desc: "JSONL session storage",
|
|
96
|
+
defaultText: "${workspace-path}/.pi/sessions",
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "client-dist-path",
|
|
100
|
+
env: "CLIENT_DIST_PATH",
|
|
101
|
+
type: "string",
|
|
102
|
+
group: "paths",
|
|
103
|
+
desc: "Built client (Vite output) dir",
|
|
104
|
+
defaultText: "(bundled with package)",
|
|
105
|
+
},
|
|
106
|
+
// auth
|
|
107
|
+
{
|
|
108
|
+
name: "ui-password",
|
|
109
|
+
env: "UI_PASSWORD",
|
|
110
|
+
type: "string",
|
|
111
|
+
group: "auth",
|
|
112
|
+
desc: "Browser login password (enables JWT auth). Use @<path> to read from a file.",
|
|
113
|
+
defaultText: "(unset, auth disabled unless --api-key)",
|
|
114
|
+
sensitive: true,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: "api-key",
|
|
118
|
+
env: "API_KEY",
|
|
119
|
+
type: "string",
|
|
120
|
+
group: "auth",
|
|
121
|
+
desc: "Static bearer token for programmatic clients. Use @<path> to read from a file.",
|
|
122
|
+
defaultText: "(unset, auth disabled unless --ui-password)",
|
|
123
|
+
sensitive: true,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: "jwt-secret",
|
|
127
|
+
env: "JWT_SECRET",
|
|
128
|
+
type: "string",
|
|
129
|
+
group: "auth",
|
|
130
|
+
desc: "JWT signing secret (auto-generated and persisted if unset). Use @<path>.",
|
|
131
|
+
defaultText: "(auto-generated)",
|
|
132
|
+
sensitive: true,
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
name: "jwt-expires-in-seconds",
|
|
136
|
+
env: "JWT_EXPIRES_IN_SECONDS",
|
|
137
|
+
type: "number",
|
|
138
|
+
group: "auth",
|
|
139
|
+
desc: "Browser JWT lifetime in seconds",
|
|
140
|
+
defaultText: "604800 (7d)",
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: "require-password-change",
|
|
144
|
+
env: "REQUIRE_PASSWORD_CHANGE",
|
|
145
|
+
type: "boolean",
|
|
146
|
+
group: "auth",
|
|
147
|
+
desc: "Require user to change password on first login (set when --ui-password is sealed-secret)",
|
|
148
|
+
defaultText: "false",
|
|
149
|
+
},
|
|
150
|
+
// features
|
|
151
|
+
{
|
|
152
|
+
name: "log-level",
|
|
153
|
+
env: "LOG_LEVEL",
|
|
154
|
+
type: "string",
|
|
155
|
+
group: "features",
|
|
156
|
+
desc: "Pino log level: trace|debug|info|warn|error|fatal",
|
|
157
|
+
defaultText: "info",
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: "serve-client",
|
|
161
|
+
env: "SERVE_CLIENT",
|
|
162
|
+
type: "boolean",
|
|
163
|
+
group: "features",
|
|
164
|
+
desc: "Serve the built React UI from this server (turn off if running Vite separately)",
|
|
165
|
+
defaultText: "true",
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: "minimal-ui",
|
|
169
|
+
env: "MINIMAL_UI",
|
|
170
|
+
type: "boolean",
|
|
171
|
+
group: "features",
|
|
172
|
+
desc: "Hide terminal/git/last-turn/settings panes; locked-down deploys",
|
|
173
|
+
defaultText: "false",
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: "hide-builtin-providers",
|
|
177
|
+
env: "HIDE_BUILTIN_PROVIDERS",
|
|
178
|
+
type: "boolean",
|
|
179
|
+
group: "features",
|
|
180
|
+
desc: "Hide built-in provider entries from the providers list",
|
|
181
|
+
defaultText: "false",
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
name: "expose-docs",
|
|
185
|
+
env: "EXPOSE_DOCS",
|
|
186
|
+
type: "boolean",
|
|
187
|
+
group: "features",
|
|
188
|
+
desc: "Expose /api/docs (Swagger UI + OpenAPI JSON)",
|
|
189
|
+
defaultText: "true",
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
name: "agent-secret-hygiene",
|
|
193
|
+
env: "AGENT_SECRET_HYGIENE_RULE",
|
|
194
|
+
type: "boolean",
|
|
195
|
+
group: "features",
|
|
196
|
+
desc: "Append a secret-hygiene rule to the agent's system prompt",
|
|
197
|
+
defaultText: "false",
|
|
198
|
+
},
|
|
199
|
+
// rate limits
|
|
200
|
+
{
|
|
201
|
+
name: "rate-limit-login-max",
|
|
202
|
+
env: "RATE_LIMIT_LOGIN_MAX",
|
|
203
|
+
type: "number",
|
|
204
|
+
group: "rate-limits",
|
|
205
|
+
desc: "Login attempts per window",
|
|
206
|
+
defaultText: "10",
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
name: "rate-limit-login-window-ms",
|
|
210
|
+
env: "RATE_LIMIT_LOGIN_WINDOW_MS",
|
|
211
|
+
type: "number",
|
|
212
|
+
group: "rate-limits",
|
|
213
|
+
desc: "Login rate-limit window (ms)",
|
|
214
|
+
defaultText: "60000",
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: "rate-limit-prompt-max",
|
|
218
|
+
env: "RATE_LIMIT_PROMPT_MAX",
|
|
219
|
+
type: "number",
|
|
220
|
+
group: "rate-limits",
|
|
221
|
+
desc: "Prompt/steer/compact/navigate calls per window",
|
|
222
|
+
defaultText: "60",
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
name: "rate-limit-prompt-window-ms",
|
|
226
|
+
env: "RATE_LIMIT_PROMPT_WINDOW_MS",
|
|
227
|
+
type: "number",
|
|
228
|
+
group: "rate-limits",
|
|
229
|
+
desc: "Prompt rate-limit window (ms)",
|
|
230
|
+
defaultText: "60000",
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
name: "rate-limit-upload-max",
|
|
234
|
+
env: "RATE_LIMIT_UPLOAD_MAX",
|
|
235
|
+
type: "number",
|
|
236
|
+
group: "rate-limits",
|
|
237
|
+
desc: "File upload calls per window",
|
|
238
|
+
defaultText: "30",
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
name: "rate-limit-upload-window-ms",
|
|
242
|
+
env: "RATE_LIMIT_UPLOAD_WINDOW_MS",
|
|
243
|
+
type: "number",
|
|
244
|
+
group: "rate-limits",
|
|
245
|
+
desc: "Upload rate-limit window (ms)",
|
|
246
|
+
defaultText: "60000",
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
name: "rate-limit-search-max",
|
|
250
|
+
env: "RATE_LIMIT_SEARCH_MAX",
|
|
251
|
+
type: "number",
|
|
252
|
+
group: "rate-limits",
|
|
253
|
+
desc: "File search calls per window",
|
|
254
|
+
defaultText: "60",
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
name: "rate-limit-search-window-ms",
|
|
258
|
+
env: "RATE_LIMIT_SEARCH_WINDOW_MS",
|
|
259
|
+
type: "number",
|
|
260
|
+
group: "rate-limits",
|
|
261
|
+
desc: "Search rate-limit window (ms)",
|
|
262
|
+
defaultText: "60000",
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
name: "rate-limit-push-max",
|
|
266
|
+
env: "RATE_LIMIT_PUSH_MAX",
|
|
267
|
+
type: "number",
|
|
268
|
+
group: "rate-limits",
|
|
269
|
+
desc: "Git push calls per window",
|
|
270
|
+
defaultText: "10",
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
name: "rate-limit-push-window-ms",
|
|
274
|
+
env: "RATE_LIMIT_PUSH_WINDOW_MS",
|
|
275
|
+
type: "number",
|
|
276
|
+
group: "rate-limits",
|
|
277
|
+
desc: "Push rate-limit window (ms)",
|
|
278
|
+
defaultText: "60000",
|
|
279
|
+
},
|
|
280
|
+
// terminal
|
|
281
|
+
{
|
|
282
|
+
name: "pty-idle-reap-ms",
|
|
283
|
+
env: "PTY_IDLE_REAP_MS",
|
|
284
|
+
type: "number",
|
|
285
|
+
group: "terminal",
|
|
286
|
+
desc: "How long a detached PTY survives before reap (ms; 0 disables reattach)",
|
|
287
|
+
defaultText: "600000 (10m)",
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
name: "terminal-passthrough-env",
|
|
291
|
+
env: "TERMINAL_PASSTHROUGH_ENV",
|
|
292
|
+
type: "list",
|
|
293
|
+
group: "terminal",
|
|
294
|
+
desc: "Extra env vars the integrated terminal inherits (comma- or space-separated)",
|
|
295
|
+
defaultText: "(empty allowlist)",
|
|
296
|
+
},
|
|
297
|
+
];
|
|
298
|
+
const FLAGS_BY_NAME = new Map(FLAGS.map((f) => [f.name, f]));
|
|
299
|
+
const BOOL_TRUE = new Set(["1", "true", "yes", "on"]);
|
|
300
|
+
const BOOL_FALSE = new Set(["0", "false", "no", "off"]);
|
|
301
|
+
/**
|
|
302
|
+
* Pre-process argv to handle `--no-<bool>` (parseArgs doesn't natively).
|
|
303
|
+
*
|
|
304
|
+
* `--no-foo` becomes `--foo=false` (only for declared boolean flags;
|
|
305
|
+
* unknown `--no-X` is left untouched so parseArgs surfaces it as a
|
|
306
|
+
* normal "Unknown option" error).
|
|
307
|
+
*/
|
|
308
|
+
function expandNegatedBooleans(args) {
|
|
309
|
+
const out = [];
|
|
310
|
+
for (const arg of args) {
|
|
311
|
+
if (arg.startsWith("--no-")) {
|
|
312
|
+
const name = arg.slice("--no-".length);
|
|
313
|
+
const def = FLAGS_BY_NAME.get(name);
|
|
314
|
+
if (def && def.type === "boolean") {
|
|
315
|
+
out.push(`--${name}=false`);
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
out.push(arg);
|
|
320
|
+
}
|
|
321
|
+
return out;
|
|
322
|
+
}
|
|
323
|
+
/** Read a sensitive flag's value, dereferencing `@<path>` syntax. */
|
|
324
|
+
function resolveSensitive(value, flagName, errors) {
|
|
325
|
+
if (!value.startsWith("@"))
|
|
326
|
+
return value;
|
|
327
|
+
const path = value.slice(1);
|
|
328
|
+
if (path === "") {
|
|
329
|
+
errors.push(`--${flagName}: @ syntax requires a path (e.g. --${flagName} @/run/secrets/key)`);
|
|
330
|
+
return undefined;
|
|
331
|
+
}
|
|
332
|
+
try {
|
|
333
|
+
return readFileSync(path, "utf8").trim();
|
|
334
|
+
}
|
|
335
|
+
catch (err) {
|
|
336
|
+
errors.push(`--${flagName}: failed to read ${path}: ${err.code ?? err.message}`);
|
|
337
|
+
return undefined;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
export function parseCliArgs(argv) {
|
|
341
|
+
const result = {
|
|
342
|
+
envWrites: [],
|
|
343
|
+
helpRequested: false,
|
|
344
|
+
versionRequested: false,
|
|
345
|
+
errors: [],
|
|
346
|
+
positionals: [],
|
|
347
|
+
};
|
|
348
|
+
const expanded = expandNegatedBooleans(argv);
|
|
349
|
+
const options = {
|
|
350
|
+
help: { type: "boolean", short: "h" },
|
|
351
|
+
version: { type: "boolean", short: "v" },
|
|
352
|
+
};
|
|
353
|
+
for (const f of FLAGS) {
|
|
354
|
+
if (f.type === "boolean") {
|
|
355
|
+
// Accept bare `--foo` (parsed as boolean true) and `--foo=value` (string).
|
|
356
|
+
// parseArgs can't represent both — pick string, treat presence-without-value
|
|
357
|
+
// by inserting "=true" in pre-pass.
|
|
358
|
+
options[f.name] = { type: "string" };
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
options[f.name] = { type: "string" };
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
// Second pre-pass: bare `--bool-flag` with no following arg (or a
|
|
365
|
+
// following arg that looks like another flag) → `--bool-flag=true`.
|
|
366
|
+
// Otherwise we leave it alone so parseArgs grabs the next arg as the
|
|
367
|
+
// value, and the bool-coercion step below produces a precise
|
|
368
|
+
// "expected a boolean" error rather than a generic "unexpected
|
|
369
|
+
// positional" complaint.
|
|
370
|
+
const finalArgs = [];
|
|
371
|
+
for (let i = 0; i < expanded.length; i++) {
|
|
372
|
+
const arg = expanded[i];
|
|
373
|
+
if (arg === undefined)
|
|
374
|
+
continue;
|
|
375
|
+
if (arg.startsWith("--") && !arg.includes("=")) {
|
|
376
|
+
const name = arg.slice(2);
|
|
377
|
+
const def = FLAGS_BY_NAME.get(name);
|
|
378
|
+
if (def && def.type === "boolean") {
|
|
379
|
+
const next = expanded[i + 1];
|
|
380
|
+
if (next === undefined || next.startsWith("--") || next.startsWith("-")) {
|
|
381
|
+
finalArgs.push(`--${name}=true`);
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
finalArgs.push(arg);
|
|
387
|
+
}
|
|
388
|
+
let parsed;
|
|
389
|
+
try {
|
|
390
|
+
parsed = parseArgs({
|
|
391
|
+
args: finalArgs,
|
|
392
|
+
options,
|
|
393
|
+
allowPositionals: true,
|
|
394
|
+
strict: true,
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
catch (err) {
|
|
398
|
+
result.errors.push(err.message);
|
|
399
|
+
return result;
|
|
400
|
+
}
|
|
401
|
+
result.positionals = parsed.positionals;
|
|
402
|
+
if (parsed.values.help === true)
|
|
403
|
+
result.helpRequested = true;
|
|
404
|
+
if (parsed.values.version === true)
|
|
405
|
+
result.versionRequested = true;
|
|
406
|
+
if (parsed.positionals.length > 0) {
|
|
407
|
+
result.errors.push(`Unexpected positional argument(s): ${parsed.positionals.join(", ")}. ` +
|
|
408
|
+
`pi-forge takes flags only — see --help.`);
|
|
409
|
+
}
|
|
410
|
+
for (const f of FLAGS) {
|
|
411
|
+
const raw = parsed.values[f.name];
|
|
412
|
+
if (raw === undefined)
|
|
413
|
+
continue;
|
|
414
|
+
const rawStr = String(raw);
|
|
415
|
+
if (f.type === "boolean") {
|
|
416
|
+
const lc = rawStr.toLowerCase();
|
|
417
|
+
if (BOOL_TRUE.has(lc)) {
|
|
418
|
+
result.envWrites.push({ key: f.env, value: "true" });
|
|
419
|
+
}
|
|
420
|
+
else if (BOOL_FALSE.has(lc)) {
|
|
421
|
+
result.envWrites.push({ key: f.env, value: "false" });
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
result.errors.push(`--${f.name}: expected a boolean (true/false/on/off/1/0/yes/no), got ${JSON.stringify(rawStr)}`);
|
|
425
|
+
}
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
if (f.type === "number") {
|
|
429
|
+
const n = Number.parseInt(rawStr, 10);
|
|
430
|
+
if (!Number.isFinite(n) || n < 0 || String(n) !== rawStr.trim()) {
|
|
431
|
+
result.errors.push(`--${f.name}: expected a non-negative integer, got ${JSON.stringify(rawStr)}`);
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
result.envWrites.push({ key: f.env, value: String(n) });
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
437
|
+
if (f.sensitive) {
|
|
438
|
+
const resolved = resolveSensitive(rawStr, f.name, result.errors);
|
|
439
|
+
if (resolved === undefined)
|
|
440
|
+
continue;
|
|
441
|
+
if (resolved === "") {
|
|
442
|
+
result.errors.push(`--${f.name}: resolved value is empty`);
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
result.envWrites.push({ key: f.env, value: resolved });
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
// string + list pass through verbatim — config.ts parses lists.
|
|
449
|
+
result.envWrites.push({ key: f.env, value: rawStr });
|
|
450
|
+
}
|
|
451
|
+
return result;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Apply parsed env writes. Flag values WIN over any pre-existing env,
|
|
455
|
+
* matching the documented "flag overrides env" rule.
|
|
456
|
+
*/
|
|
457
|
+
export function applyCliEnv(parsed) {
|
|
458
|
+
for (const { key, value } of parsed.envWrites) {
|
|
459
|
+
process.env[key] = value;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
const GROUP_LABELS = {
|
|
463
|
+
network: "Network",
|
|
464
|
+
paths: "Paths",
|
|
465
|
+
auth: "Authentication",
|
|
466
|
+
features: "Features",
|
|
467
|
+
"rate-limits": "Rate limits",
|
|
468
|
+
terminal: "Terminal",
|
|
469
|
+
};
|
|
470
|
+
export function buildHelpText(version) {
|
|
471
|
+
const out = [];
|
|
472
|
+
out.push(`pi-forge ${version}`);
|
|
473
|
+
out.push("");
|
|
474
|
+
out.push("Browser UI for the pi coding agent.");
|
|
475
|
+
out.push("");
|
|
476
|
+
out.push("Usage:");
|
|
477
|
+
out.push(" pi-forge [options]");
|
|
478
|
+
out.push("");
|
|
479
|
+
out.push("Every option below has an equivalent environment variable. Flags win when both are set.");
|
|
480
|
+
out.push("");
|
|
481
|
+
const groups = ["network", "paths", "auth", "features", "rate-limits", "terminal"];
|
|
482
|
+
for (const group of groups) {
|
|
483
|
+
const flags = FLAGS.filter((f) => f.group === group);
|
|
484
|
+
if (flags.length === 0)
|
|
485
|
+
continue;
|
|
486
|
+
out.push(`${GROUP_LABELS[group]}:`);
|
|
487
|
+
const longest = Math.max(...flags.map((f) => f.name.length + (f.type === "boolean" ? 0 : 6)));
|
|
488
|
+
for (const f of flags) {
|
|
489
|
+
const flagCol = f.type === "boolean" ? `--${f.name}` : `--${f.name} <val>`;
|
|
490
|
+
const padded = flagCol.padEnd(longest + 4, " ");
|
|
491
|
+
out.push(` ${padded}${f.desc}`);
|
|
492
|
+
out.push(` ${"".padEnd(longest + 4, " ")}env: ${f.env}; default: ${f.defaultText}`);
|
|
493
|
+
}
|
|
494
|
+
out.push("");
|
|
495
|
+
}
|
|
496
|
+
out.push("Other:");
|
|
497
|
+
out.push(" --help, -h Show this help and exit");
|
|
498
|
+
out.push(" --version, -v Print version and exit");
|
|
499
|
+
out.push("");
|
|
500
|
+
out.push("Boolean flags accept true/false/on/off/1/0/yes/no, or use --no-<flag> for false.");
|
|
501
|
+
out.push("Sensitive flags (--ui-password, --api-key, --jwt-secret) accept @<path> to read from file.");
|
|
502
|
+
out.push("");
|
|
503
|
+
out.push("Examples:");
|
|
504
|
+
out.push(" pi-forge --port 4000 --workspace-path ~/Code");
|
|
505
|
+
out.push(" pi-forge --api-key @/run/secrets/api-key");
|
|
506
|
+
out.push(" pi-forge --no-expose-docs --minimal-ui");
|
|
507
|
+
out.push("");
|
|
508
|
+
return out.join("\n");
|
|
509
|
+
}
|
|
510
|
+
/** Exposed so tests can iterate the same source of truth. */
|
|
511
|
+
export const FLAG_DEFS = FLAGS;
|
|
512
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/server/config.js
CHANGED
|
@@ -92,6 +92,7 @@ const CLIENT_DIST_PATH = resolve(readEnv("CLIENT_DIST_PATH") ??
|
|
|
92
92
|
const UI_PASSWORD = readEnv("UI_PASSWORD");
|
|
93
93
|
const API_KEY = readEnv("API_KEY");
|
|
94
94
|
const CORS_ORIGIN = readEnv("CORS_ORIGIN");
|
|
95
|
+
const PASSWORD_HASH_FILE = join(FORGE_DATA_DIR, "password-hash");
|
|
95
96
|
/**
|
|
96
97
|
* Load a JWT signing key from `${FORGE_DATA_DIR}/jwt-secret`, or
|
|
97
98
|
* generate-and-persist one on first boot. Treated like an SSH host key:
|
|
@@ -99,8 +100,13 @@ const CORS_ORIGIN = readEnv("CORS_ORIGIN");
|
|
|
99
100
|
* in K8s and Docker), reused across restarts so issued tokens stay
|
|
100
101
|
* valid. Setting `JWT_SECRET` env explicitly skips this entirely.
|
|
101
102
|
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
103
|
+
* Invoked when ANY browser-auth credential is in play: an env-supplied
|
|
104
|
+
* `UI_PASSWORD`, or a previously-persisted password-hash file (the
|
|
105
|
+
* latter survives env rotation, the same way jwt-secret does).
|
|
106
|
+
* Without this, a deployment that booted with `UI_PASSWORD` once and
|
|
107
|
+
* then dropped it after the user changed their password would be left
|
|
108
|
+
* with a hash on disk but no signing key — login would 500 trying to
|
|
109
|
+
* sign a JWT with `undefined`.
|
|
104
110
|
*/
|
|
105
111
|
function loadOrGenerateJwtSecret(dataDir) {
|
|
106
112
|
const path = join(dataDir, "jwt-secret");
|
|
@@ -122,15 +128,19 @@ function loadOrGenerateJwtSecret(dataDir) {
|
|
|
122
128
|
return secret;
|
|
123
129
|
}
|
|
124
130
|
const JWT_SECRET = readEnv("JWT_SECRET") ??
|
|
125
|
-
(UI_PASSWORD !== undefined
|
|
131
|
+
(UI_PASSWORD !== undefined || existsSync(PASSWORD_HASH_FILE)
|
|
132
|
+
? loadOrGenerateJwtSecret(FORGE_DATA_DIR)
|
|
133
|
+
: undefined);
|
|
126
134
|
export const config = Object.freeze({
|
|
127
135
|
port: readInt("PORT", 3000),
|
|
128
|
-
// HOST
|
|
129
|
-
//
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
|
|
136
|
+
// HOST defaults to 127.0.0.1 in every mode. Binding loopback by
|
|
137
|
+
// default protects against silently exposing the agent's shell +
|
|
138
|
+
// filesystem to anyone on the same WiFi/VLAN/bridge — an opt-in,
|
|
139
|
+
// not an opt-out. Operators who want LAN access (or container-host
|
|
140
|
+
// port-forwarding to work) set `HOST=0.0.0.0` explicitly. The
|
|
141
|
+
// shipped Docker image does this in its Dockerfile so the
|
|
142
|
+
// documented `docker compose up` flow keeps working out of the box.
|
|
143
|
+
host: readEnv("HOST") ?? "127.0.0.1",
|
|
134
144
|
logLevel: readEnv("LOG_LEVEL") ?? "info",
|
|
135
145
|
isTest: (readEnv("NODE_ENV") ?? "") === "test",
|
|
136
146
|
trustProxy: readBool("TRUST_PROXY", false),
|
|
@@ -228,13 +238,18 @@ export const config = Object.freeze({
|
|
|
228
238
|
* is hashed and persisted to `${FORGE_DATA_DIR}/password-hash`,
|
|
229
239
|
* and subsequent logins ignore the env value.
|
|
230
240
|
*
|
|
231
|
-
* Defaults to
|
|
232
|
-
*
|
|
233
|
-
*
|
|
241
|
+
* Defaults to false: pi-forge is single-tenant and the user
|
|
242
|
+
* setting `--ui-password` / `UI_PASSWORD` does so deliberately,
|
|
243
|
+
* so forcing them to immediately pick a different password is
|
|
244
|
+
* friction without a meaningful threat-model win. Deployments
|
|
245
|
+
* that bake an initial sealed-secret password into env (helm,
|
|
246
|
+
* docker-compose .env) and want the operator to swap it after
|
|
247
|
+
* first login can opt back in with `--require-password-change`
|
|
248
|
+
* (or `REQUIRE_PASSWORD_CHANGE=true`).
|
|
234
249
|
*/
|
|
235
|
-
requirePasswordChange: readBool("REQUIRE_PASSWORD_CHANGE",
|
|
250
|
+
requirePasswordChange: readBool("REQUIRE_PASSWORD_CHANGE", false),
|
|
236
251
|
/** Where the persisted scrypt hash lives — see auth.ts. */
|
|
237
|
-
passwordHashFile:
|
|
252
|
+
passwordHashFile: PASSWORD_HASH_FILE,
|
|
238
253
|
}),
|
|
239
254
|
/**
|
|
240
255
|
* Per-route rate limits applied to the cost-heavy / disk-heavy / CPU-heavy
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACpG,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,SAAS,OAAO,CAAC,GAAW;IAC1B,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,OAAO,CAAC,GAAW,EAAE,QAAgB;IAC5C,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACvB,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACrC,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,WAAW,GAAG,wCAAwC,CAAC,GAAG,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,cAAc,CAAC,GAAW;IACjC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACvB,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IAC/B,kEAAkE;IAClE,gEAAgE;IAChE,+CAA+C;IAC/C,OAAO,CAAC;SACL,KAAK,CAAC,QAAQ,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW,EAAE,QAAiB;IAC9C,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC;IACtC,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACrC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACxD,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1D,MAAM,IAAI,KAAK,CAAC,WAAW,GAAG,qCAAqC,CAAC,GAAG,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;AACvB,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;IAChC,MAAM,IAAI,KAAK,CACb,iCAAiC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI;QACvD,kDAAkD;QAClD,oEAAoE;QACpE,6CAA6C,CAChD,CAAC;AACJ,CAAC;AACD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;AAC3C,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;AAC3F,6EAA6E;AAC7E,0EAA0E;AAC1E,6EAA6E;AAC7E,iEAAiE;AACjE,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AACtF,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,GAAG,cAAc,eAAe,CAAC,CAAC;AACxF;;;;;;;;GAQG;AACH,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,UAAU,CAAC,CAAC;AAExE;;;;;;;;GAQG;AACH,MAAM,gBAAgB,GAAG,OAAO,CAC9B,OAAO,CAAC,kBAAkB,CAAC;IACzB,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAC9E,CAAC;AAEF,MAAM,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AACnC,MAAM,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-forge",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Browser UI for the pi coding agent — embedded HTTP server with a React workbench (chat, file browser, terminal, git, MCP).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@fastify/cors": "^11.0.1",
|
|
42
|
-
"@fastify/multipart": "^
|
|
42
|
+
"@fastify/multipart": "^10.0.0",
|
|
43
43
|
"@fastify/rate-limit": "^10.2.2",
|
|
44
44
|
"@fastify/static": "^9.1.3",
|
|
45
45
|
"@fastify/swagger": "^9.5.0",
|