pi-forge 1.1.5 → 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-EHkmefTD.js → CodeMirrorEditor-DXdXoCjw.js} +2 -2
- package/dist/client/assets/{CodeMirrorEditor-EHkmefTD.js.map → CodeMirrorEditor-DXdXoCjw.js.map} +1 -1
- package/dist/client/assets/index-DRa0fybV.js +356 -0
- 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/agent-resource-loader.js +31 -10
- package/dist/server/agent-resource-loader.js.map +1 -1
- package/dist/server/cli.js +512 -0
- package/dist/server/cli.js.map +1 -0
- package/dist/server/config-export.js +36 -8
- package/dist/server/config-export.js.map +1 -1
- package/dist/server/config-manager.js +124 -1
- package/dist/server/config-manager.js.map +1 -1
- package/dist/server/config.js +40 -14
- package/dist/server/config.js.map +1 -1
- package/dist/server/project-manager.js +4 -0
- package/dist/server/project-manager.js.map +1 -1
- package/dist/server/prompt-overrides.js +131 -0
- package/dist/server/prompt-overrides.js.map +1 -0
- package/dist/server/routes/config.js +231 -14
- package/dist/server/routes/config.js.map +1 -1
- package/dist/server/session-registry.js +14 -6
- package/dist/server/session-registry.js.map +1 -1
- package/package.json +2 -2
- package/dist/client/assets/index-5KN1PFqY.css +0 -1
- package/dist/client/assets/index-B0ffzJ0t.js +0 -356
- package/dist/client/assets/index-B0ffzJ0t.js.map +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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"}
|
|
@@ -2,9 +2,24 @@
|
|
|
2
2
|
* Config export / import as a flat `.tar.gz`.
|
|
3
3
|
*
|
|
4
4
|
* What's included (and why):
|
|
5
|
-
* - `mcp.json`
|
|
6
|
-
* - `settings.json`
|
|
7
|
-
* - `models.json`
|
|
5
|
+
* - `mcp.json` — pi-forge-owned MCP server registry
|
|
6
|
+
* - `settings.json` — pi-owned defaults (model, thinking level, skills patterns)
|
|
7
|
+
* - `models.json` — pi-owned custom providers
|
|
8
|
+
* - `skills-overrides.json` — pi-forge-private per-project skill enable/disable state
|
|
9
|
+
* - `tool-overrides.json` — pi-forge-private per-project tool enable/disable state
|
|
10
|
+
*
|
|
11
|
+
* The two `*-overrides.json` files live in `${FORGE_DATA_DIR}` (not
|
|
12
|
+
* `${PI_CONFIG_DIR}` like the other three). They're included because
|
|
13
|
+
* the user's per-project tool/skill toggle decisions are part of "the
|
|
14
|
+
* pi-forge config a power-user wants to carry across installations" —
|
|
15
|
+
* pairing a backup of `settings.json` (global skill patterns) without
|
|
16
|
+
* also backing up the per-project overrides loses information.
|
|
17
|
+
* `projectId`s in the overrides files are local UUIDs — re-importing
|
|
18
|
+
* onto an installation with a different `projects.json` will leave
|
|
19
|
+
* orphan entries that are silently ignored at session-create time.
|
|
20
|
+
* Acceptable trade-off; the alternative (refusing to import overrides
|
|
21
|
+
* when project IDs don't match) would defeat the point of carrying
|
|
22
|
+
* per-project config across installs that share workspaces.
|
|
8
23
|
*
|
|
9
24
|
* What's deliberately EXCLUDED:
|
|
10
25
|
* - `auth.json` — provider API keys + OAuth tokens. OAuth tokens are
|
|
@@ -14,12 +29,14 @@
|
|
|
14
29
|
* (Slack, Drive, ticket attachment) outweighs the convenience. The
|
|
15
30
|
* import flow tells the user to re-authenticate providers
|
|
16
31
|
* afterwards.
|
|
32
|
+
* - `projects.json` — installation-bound (project paths reference
|
|
33
|
+
* local disk locations that won't exist on the target machine).
|
|
17
34
|
* - The auto-generated `jwt-secret` and `password-hash` files —
|
|
18
35
|
* installation-bound, intentionally not portable.
|
|
19
36
|
*
|
|
20
|
-
* Archive layout: a flat tar with the
|
|
37
|
+
* Archive layout: a flat tar with the files at the top level (no
|
|
21
38
|
* leading directory). Importing rejects any entry that isn't one of
|
|
22
|
-
*
|
|
39
|
+
* the allow-listed names — this is the only validation that matters
|
|
23
40
|
* for safety, since the names map deterministically to disk targets.
|
|
24
41
|
*
|
|
25
42
|
* Atomic writes: each imported file lands in `<dst>.import.tmp` first,
|
|
@@ -40,17 +57,28 @@ import { config } from "./config.js";
|
|
|
40
57
|
* entry and we can't accidentally accept a near-miss like
|
|
41
58
|
* `Settings.json` on a case-sensitive filesystem.
|
|
42
59
|
*/
|
|
43
|
-
const ALLOWED_FILES = [
|
|
60
|
+
const ALLOWED_FILES = [
|
|
61
|
+
"mcp.json",
|
|
62
|
+
"settings.json",
|
|
63
|
+
"models.json",
|
|
64
|
+
"skills-overrides.json",
|
|
65
|
+
"tool-overrides.json",
|
|
66
|
+
];
|
|
44
67
|
const ALLOWED_SET = new Set(ALLOWED_FILES);
|
|
45
68
|
/**
|
|
46
69
|
* Map each allowed name to its on-disk target. Functions (not
|
|
47
|
-
* constants) so changes to `config.piConfigDir` /
|
|
48
|
-
* `config.mcpConfigFile` at test time take effect.
|
|
70
|
+
* constants) so changes to `config.piConfigDir` / `config.forgeDataDir`
|
|
71
|
+
* / `config.mcpConfigFile` at test time take effect. The two
|
|
72
|
+
* `*-overrides.json` files live under FORGE_DATA_DIR, NOT PI_CONFIG_DIR
|
|
73
|
+
* — pi-forge-private state, intentionally not commingled with the
|
|
74
|
+
* SDK's directory.
|
|
49
75
|
*/
|
|
50
76
|
const TARGETS = {
|
|
51
77
|
"mcp.json": () => config.mcpConfigFile,
|
|
52
78
|
"settings.json": () => join(config.piConfigDir, "settings.json"),
|
|
53
79
|
"models.json": () => join(config.piConfigDir, "models.json"),
|
|
80
|
+
"skills-overrides.json": () => config.skillOverridesFile,
|
|
81
|
+
"tool-overrides.json": () => config.toolOverridesFile,
|
|
54
82
|
};
|
|
55
83
|
/**
|
|
56
84
|
* Hard cap on uploaded tar size. Far above the realistic config size
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-export.js","sourceRoot":"","sources":["../src/config-export.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"config-export.js","sourceRoot":"","sources":["../src/config-export.ts"],"names":[],"mappings":"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"}
|