@wrongstack/cli 1.1.2 → 1.1.5
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/dist/{acp-HCGUTFNE.js → acp-NKUEYJDZ.js} +14 -5
- package/dist/acp-leader/acp-leader-confirm.d.ts +20 -0
- package/dist/acp-leader/acp-leader-context.d.ts +29 -0
- package/dist/acp-leader/acp-leader-fleet.d.ts +26 -0
- package/dist/acp-leader/acp-leader-host-binding.d.ts +17 -0
- package/dist/acp-leader/acp-leader-host.d.ts +82 -0
- package/dist/acp-leader/acp-leader-picker.d.ts +24 -0
- package/dist/acp-leader/acp-leader-provider.d.ts +85 -0
- package/dist/acp-leader/acp-leader-resume.d.ts +10 -0
- package/dist/acp-leader/acp-leader-stream.d.ts +83 -0
- package/dist/{auth-ANOVZVHE.js → auth-2ZG5DBHS.js} +62 -66
- package/dist/auth-menu/index.d.ts +1 -2
- package/dist/boot/dispatch-webui.d.ts +16 -0
- package/dist/boot/launch-menu-arrow.d.ts +20 -0
- package/dist/boot/launch-menu-types.d.ts +36 -0
- package/dist/boot/launch-menu.d.ts +1 -57
- package/dist/boot/tui-session-resume-rollback.d.ts +31 -0
- package/dist/{boot-auto-thin-7D4OVEWA.js → boot-auto-thin-N2CIGTXE.js} +3 -3
- package/dist/{chunk-TZPKOS5G.js → chunk-2XQ6SRKG.js} +2 -2
- package/dist/chunk-3LEIFO5D.js +65 -0
- package/dist/chunk-5SGMUDP5.js +752 -0
- package/dist/{chunk-3EXRPTAU.js → chunk-5TQ65PXQ.js} +17 -17
- package/dist/{chunk-GRAGMA4B.js → chunk-7BM4LGKQ.js} +18 -18
- package/dist/{chunk-VAQXOZKP.js → chunk-AJM4EFCM.js} +139 -136
- package/dist/{chunk-C2BBH4S4.js → chunk-E3MJFAFR.js} +2 -2
- package/dist/{chunk-5TRZZHMN.js → chunk-JCZ2D3VV.js} +4 -65
- package/dist/{chunk-AWRZWPJ3.js → chunk-JFYQGMMM.js} +99 -75
- package/dist/{chunk-BIGSVBPI.js → chunk-KNYIEQAY.js} +64 -61
- package/dist/chunk-LUEO5HLZ.js +50 -0
- package/dist/chunk-LYWOV4OX.js +252 -0
- package/dist/chunk-M7FNHCE3.js +2070 -0
- package/dist/{chunk-75OLD563.js → chunk-M7PSENGF.js} +3 -1
- package/dist/{chunk-NMXQFQ26.js → chunk-MEBXWI7U.js} +5 -5
- package/dist/{chunk-RAWHRRUJ.js → chunk-MKMM5RIW.js} +209 -201
- package/dist/{chunk-3R3OADC5.js → chunk-P7MEEUGT.js} +281 -252
- package/dist/chunk-QLYPIJ7X.js +258 -0
- package/dist/chunk-RN5CFAVQ.js +292 -0
- package/dist/{chunk-WDXNBYGD.js → chunk-TDP7CZGE.js} +6 -1
- package/dist/{chunk-6VPWQ4TG.js → chunk-UROB7MK5.js} +2 -1
- package/dist/chunk-VEESMPTX.js +254 -0
- package/dist/{chunk-IJLIAPCW.js → chunk-VPSAKGLK.js} +47 -47
- package/dist/{cli-context-YIT4FEDM.js → cli-context-CQYGIWOU.js} +254 -237
- package/dist/{cli-main-JIADJ5OL.js → cli-main-VRUJNUBX.js} +2081 -1594
- package/dist/cli-main-boot.d.ts +1 -1
- package/dist/config-doctor-known-keys.d.ts +33 -0
- package/dist/config-doctor.d.ts +2 -47
- package/dist/config-history-support.d.ts +36 -0
- package/dist/config-history.d.ts +1 -1
- package/dist/{config-transfer-Y7XJMJRN.js → config-transfer-B4GOZTFC.js} +2 -2
- package/dist/{execution-BAP566QC.js → execution-IV72RUSM.js} +5354 -5258
- package/dist/execution-tui.d.ts +30 -0
- package/dist/fleet/acp-live-steer.d.ts +28 -0
- package/dist/fleet/acp-permission-bridge.d.ts +49 -0
- package/dist/fleet/acp-quota-hold.d.ts +3 -0
- package/dist/fleet/acp-quota-reading.d.ts +3 -0
- package/dist/fleet/acp-turn-reminders.d.ts +15 -0
- package/dist/fleet/acp-wrongstack-bridge.d.ts +50 -0
- package/dist/fleet/host-acp.d.ts +23 -2
- package/dist/fleet/wrongforge-client.d.ts +116 -0
- package/dist/fleet/wrongforge-gateway.d.ts +20 -0
- package/dist/fleet/wrongforge-info.d.ts +32 -0
- package/dist/fleet/wrongforge-quota.d.ts +10 -0
- package/dist/fleet/wrongforge-runner.d.ts +37 -0
- package/dist/fleet/wrongforge-runtime.d.ts +10 -0
- package/dist/{hq-JD5AZVMG.js → hq-54PQYR5O.js} +311 -307
- package/dist/hq-server/sweeps.d.ts +28 -0
- package/dist/{hq-server-BI23EPM7.js → hq-server-YK7FBLL6.js} +3 -3
- package/dist/index.js +8 -5
- package/dist/mcp-22CFBX4H.js +236 -0
- package/dist/mcp-serve-project.d.ts +18 -0
- package/dist/mcp-serve.d.ts +0 -63
- package/dist/{modeldiag-HDIKG37X.js → modeldiag-5PBB777J.js} +4 -4
- package/dist/{per-subcommand-help-D6J4ZXW2.js → per-subcommand-help-MQGERD4E.js} +2 -2
- package/dist/plugin-llm-command.d.ts +9 -0
- package/dist/{plugin-usage-TYF5HY4K.js → plugin-usage-UWKYMNQU.js} +3 -3
- package/dist/{plugins-XGAXDLPT.js → plugins-VP7JQH47.js} +4 -4
- package/dist/{sdd-runtime-6MFUXWJK.js → sdd-runtime-HIJ4Z5TF.js} +2 -2
- package/dist/services/sdd/state.d.ts +2 -0
- package/dist/session-event-wiring-types.d.ts +62 -0
- package/dist/session-event-wiring.d.ts +2 -52
- package/dist/{sessions-config-SJVQXCIE.js → sessions-config-7MK742OW.js} +2 -2
- package/dist/short-circuit-flags-AGHURHMQ.js +11 -0
- package/dist/slash-commands/command-context-fleet.d.ts +187 -0
- package/dist/slash-commands/command-context-sdd-goal.d.ts +102 -0
- package/dist/slash-commands/command-context.d.ts +3 -282
- package/dist/slash-commands/project-switch-interactive.d.ts +11 -0
- package/dist/slash-commands/setmodel-helpers.d.ts +36 -0
- package/dist/subcommands/handlers/hq-token.d.ts +3 -0
- package/dist/subcommands/handlers/hq.d.ts +0 -21
- package/dist/subcommands/handlers/per-subcommand-help-operations.d.ts +8 -0
- package/dist/subcommands/handlers/tools-cli-args.d.ts +57 -0
- package/dist/subcommands/handlers/tools-cli.d.ts +5 -0
- package/dist/subcommands/handlers/tools-serve.d.ts +4 -0
- package/dist/{subcommands-VTMIZQBP.js → subcommands-OCJNO57E.js} +2 -2
- package/dist/tool-gateway-http.d.ts +30 -0
- package/dist/tool-gateway.d.ts +185 -0
- package/dist/tools-cli-44MLIUQO.js +509 -0
- package/dist/tools-serve-TRCET2M7.js +102 -0
- package/dist/{tools-skills-55QVTMSK.js → tools-skills-WDTMCE46.js} +7 -2
- package/dist/tuneup-runtime-checks.d.ts +7 -0
- package/dist/tuneup-types.d.ts +118 -0
- package/dist/tuneup.d.ts +3 -122
- package/dist/{typesafe-YBEADNAH.js → typesafe-QLSMFU7J.js} +1 -1
- package/dist/{version-help-RBZC5GZZ.js → version-help-X6CC4CFY.js} +2 -2
- package/dist/{webui-server-HIUY3RHD.js → webui-server-V2R5WQUK.js} +79 -3
- package/dist/wiring/provider-runtime-setup.d.ts +3 -1
- package/dist/wiring/session-runtime.d.ts +1 -1
- package/dist/wrongforge-gateway-UOFBK56J.js +92 -0
- package/dist/wrongforge-leader/wrongforge-leader-gateway.d.ts +9 -0
- package/dist/wrongforge-leader/wrongforge-leader-picker.d.ts +12 -0
- package/dist/wrongforge-leader/wrongforge-leader-provider.d.ts +49 -0
- package/package.json +34 -30
- package/dist/auth-menu/anthropic-oauth.d.ts +0 -43
- package/dist/chunk-XT3NAHRX.js +0 -337
- package/dist/chunk-ZNNFEKDZ.js +0 -319
- package/dist/mcp-2XWBJEQN.js +0 -464
- package/dist/short-circuit-flags-CPCT5MWB.js +0 -11
|
@@ -3,11 +3,6 @@ import {
|
|
|
3
3
|
resolveJsonSchemaFlag
|
|
4
4
|
} from "./chunk-VI2HE4A5.js";
|
|
5
5
|
import {
|
|
6
|
-
parseWebuiSessionChildOptions,
|
|
7
|
-
writeWebuiSessionChildError
|
|
8
|
-
} from "./chunk-FUJHWQV4.js";
|
|
9
|
-
import {
|
|
10
|
-
activateRestrictedMode,
|
|
11
6
|
announceSafeMode,
|
|
12
7
|
applySimpleUiFullAutoProfile,
|
|
13
8
|
detectProjectFacts,
|
|
@@ -17,10 +12,17 @@ import {
|
|
|
17
12
|
renderDiff,
|
|
18
13
|
resolveLaunchAllowedTools,
|
|
19
14
|
resolveToolRestriction
|
|
20
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-JCZ2D3VV.js";
|
|
21
16
|
import {
|
|
22
17
|
theme as theme2
|
|
23
18
|
} from "./chunk-JTTV2EVA.js";
|
|
19
|
+
import {
|
|
20
|
+
parseWebuiSessionChildOptions,
|
|
21
|
+
writeWebuiSessionChildError
|
|
22
|
+
} from "./chunk-FUJHWQV4.js";
|
|
23
|
+
import {
|
|
24
|
+
handleHelpVersionShortCircuit
|
|
25
|
+
} from "./chunk-MEBXWI7U.js";
|
|
24
26
|
import {
|
|
25
27
|
fmtTok,
|
|
26
28
|
patchConfig
|
|
@@ -30,24 +32,21 @@ import {
|
|
|
30
32
|
} from "./chunk-NL2ABOAS.js";
|
|
31
33
|
import {
|
|
32
34
|
subcommands
|
|
33
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-7BM4LGKQ.js";
|
|
34
36
|
import {
|
|
35
37
|
renderDeepHelp,
|
|
36
38
|
renderFocusedHelp
|
|
37
|
-
} from "./chunk-
|
|
38
|
-
import {
|
|
39
|
-
handleHelpVersionShortCircuit
|
|
40
|
-
} from "./chunk-NMXQFQ26.js";
|
|
39
|
+
} from "./chunk-P7MEEUGT.js";
|
|
41
40
|
import {
|
|
42
41
|
DEFAULT_PORT
|
|
43
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-JFYQGMMM.js";
|
|
44
43
|
import "./chunk-QVITQ425.js";
|
|
45
44
|
import {
|
|
46
45
|
resolveHqPasswordInput
|
|
47
46
|
} from "./chunk-HQBY6OFT.js";
|
|
48
47
|
import {
|
|
49
48
|
normalizeHqPublicOrigin
|
|
50
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-5TQ65PXQ.js";
|
|
51
50
|
import {
|
|
52
51
|
parseHqIpAllowlist
|
|
53
52
|
} from "./chunk-OGVSKS4Q.js";
|
|
@@ -69,7 +68,7 @@ import {
|
|
|
69
68
|
runPicker,
|
|
70
69
|
saveToGlobalConfig,
|
|
71
70
|
theme
|
|
72
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-MKMM5RIW.js";
|
|
73
72
|
import "./chunk-ZXX3MJRL.js";
|
|
74
73
|
import {
|
|
75
74
|
isKeylessLocalProvider,
|
|
@@ -81,7 +80,13 @@ import {
|
|
|
81
80
|
import {
|
|
82
81
|
activeProfileConfigPath
|
|
83
82
|
} from "./chunk-SPSHEZ46.js";
|
|
84
|
-
import "./chunk-
|
|
83
|
+
import "./chunk-KNYIEQAY.js";
|
|
84
|
+
import {
|
|
85
|
+
activateRestrictedMode
|
|
86
|
+
} from "./chunk-3LEIFO5D.js";
|
|
87
|
+
import {
|
|
88
|
+
WRONGFORGE_AGENT_ID
|
|
89
|
+
} from "./chunk-VEESMPTX.js";
|
|
85
90
|
import "./chunk-OZCYZYN2.js";
|
|
86
91
|
import {
|
|
87
92
|
runUpdateCommand
|
|
@@ -95,12 +100,15 @@ import {
|
|
|
95
100
|
} from "./chunk-CVVQ5NCN.js";
|
|
96
101
|
import {
|
|
97
102
|
parseArgs
|
|
98
|
-
} from "./chunk-
|
|
103
|
+
} from "./chunk-M7PSENGF.js";
|
|
104
|
+
import {
|
|
105
|
+
ACP_LEADER_PROVIDER_ID
|
|
106
|
+
} from "./chunk-LUEO5HLZ.js";
|
|
99
107
|
import "./chunk-H53EXXAU.js";
|
|
100
108
|
import {
|
|
101
109
|
applyAsciiMode
|
|
102
110
|
} from "./chunk-UVF3BGET.js";
|
|
103
|
-
import "./chunk-
|
|
111
|
+
import "./chunk-UROB7MK5.js";
|
|
104
112
|
import {
|
|
105
113
|
CLI_VERSION
|
|
106
114
|
} from "./chunk-HKMOIIPQ.js";
|
|
@@ -236,7 +244,7 @@ function wireContainer(deps) {
|
|
|
236
244
|
// src/boot/launch-menu.ts
|
|
237
245
|
import * as fs from "node:fs/promises";
|
|
238
246
|
import { HQ_CLI_DEFAULT_HOST } from "@wrongstack/core/hq";
|
|
239
|
-
import { atomicWrite, color, isStdinTTY
|
|
247
|
+
import { atomicWrite, color as color2, isStdinTTY as isStdinTTY2, withFileLock } from "@wrongstack/core/utils";
|
|
240
248
|
|
|
241
249
|
// src/boot/launch-banner.ts
|
|
242
250
|
var STACK_ORANGE = { r: 253, g: 159, b: 2 };
|
|
@@ -349,20 +357,15 @@ function launchBannerLines(columns, version) {
|
|
|
349
357
|
];
|
|
350
358
|
}
|
|
351
359
|
|
|
352
|
-
// src/boot/launch-menu.ts
|
|
360
|
+
// src/boot/launch-menu-arrow.ts
|
|
361
|
+
import { color, isStdinTTY, setRawMode } from "@wrongstack/core/utils";
|
|
362
|
+
|
|
363
|
+
// src/boot/launch-menu-types.ts
|
|
353
364
|
var DEFAULT_PORTS = {
|
|
354
365
|
webui: 3456,
|
|
355
366
|
simpleui: 3466,
|
|
356
367
|
hq: DEFAULT_PORT
|
|
357
368
|
};
|
|
358
|
-
var DEFAULT_HOST = "127.0.0.1";
|
|
359
|
-
var HQ_DEFAULT_HOST = HQ_CLI_DEFAULT_HOST;
|
|
360
|
-
function bindsPort(mode) {
|
|
361
|
-
return mode !== "tui-repl" && mode !== "desktop";
|
|
362
|
-
}
|
|
363
|
-
function defaultHostFor(mode) {
|
|
364
|
-
return mode === "hq" ? HQ_DEFAULT_HOST : DEFAULT_HOST;
|
|
365
|
-
}
|
|
366
369
|
var MODE_OPTIONS = [
|
|
367
370
|
{
|
|
368
371
|
key: 1,
|
|
@@ -401,88 +404,8 @@ var MODE_OPTIONS = [
|
|
|
401
404
|
}
|
|
402
405
|
];
|
|
403
406
|
var MENU_TIMEOUT_MS = 8e3;
|
|
404
|
-
var SUMMARY_TIMEOUT_MS = 5e3;
|
|
405
|
-
var PORT_TIMEOUT_MS = 8e3;
|
|
406
|
-
function shouldSkipMenu(argv, flags, positional) {
|
|
407
|
-
if (flags["no-menu"] === true) return true;
|
|
408
|
-
if (flags["webui"] === true) return true;
|
|
409
|
-
if (flags["webui-session-child"] === true) return true;
|
|
410
|
-
if (flags["simpleui"] === true) return true;
|
|
411
|
-
if (flags["hq"] === true) return true;
|
|
412
|
-
if (flags["desktop"] === true) return true;
|
|
413
|
-
if (flags["no-interactive"] === true) return true;
|
|
414
|
-
if (flags["skip"] === true) return true;
|
|
415
|
-
if (typeof flags["prompt"] === "string") return true;
|
|
416
|
-
if (!isStdinTTY()) return true;
|
|
417
|
-
if (positional.length > 0) return true;
|
|
418
|
-
void argv;
|
|
419
|
-
return false;
|
|
420
|
-
}
|
|
421
|
-
async function runLaunchMenu(deps) {
|
|
422
|
-
if (shouldSkipMenu(deps.argv, deps.flags, deps.positional)) {
|
|
423
|
-
return null;
|
|
424
|
-
}
|
|
425
|
-
const { renderer, reader, lastChoice } = deps;
|
|
426
|
-
const ports = { ...DEFAULT_PORTS, ...deps.defaultPorts ?? {} };
|
|
427
|
-
writeBanner(renderer);
|
|
428
|
-
if (lastChoice) {
|
|
429
|
-
const accept = await promptSummaryGate(deps);
|
|
430
|
-
if (accept === "use-last") {
|
|
431
|
-
return finalize(lastChoice, ports);
|
|
432
|
-
}
|
|
433
|
-
if (accept === "cancel") {
|
|
434
|
-
return { ...lastChoice, cancelled: true };
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
renderer.write(`
|
|
438
|
-
${color.amber("?")} Choose how to run WrongStack:
|
|
439
407
|
|
|
440
|
-
|
|
441
|
-
const arrowPick = await promptModeArrow(deps);
|
|
442
|
-
let choice;
|
|
443
|
-
if (arrowPick) {
|
|
444
|
-
if (arrowPick.cancelled) {
|
|
445
|
-
return { mode: "tui-repl", cancelled: true };
|
|
446
|
-
}
|
|
447
|
-
choice = { mode: arrowPick.mode };
|
|
448
|
-
} else {
|
|
449
|
-
for (const opt of MODE_OPTIONS) {
|
|
450
|
-
renderer.write(
|
|
451
|
-
` ${color.bold(String(opt.key))}) ${opt.icon} ${color.bold(opt.label)} ${color.dim(opt.hint)}
|
|
452
|
-
`
|
|
453
|
-
);
|
|
454
|
-
}
|
|
455
|
-
renderer.write(`
|
|
456
|
-
${color.dim("\u2500".repeat(48))}
|
|
457
|
-
`);
|
|
458
|
-
const answer = (await reader.readLine(
|
|
459
|
-
` ${color.amber("?")} Mode ${color.dim("[1-5, q to quit]")} ${color.dim(`(auto 1 in ${MENU_TIMEOUT_MS / 1e3}s)`)} `,
|
|
460
|
-
{ timeoutMs: MENU_TIMEOUT_MS, defaultAnswer: "1" }
|
|
461
|
-
)).trim().toLowerCase();
|
|
462
|
-
if (answer === "q" || answer === "quit") {
|
|
463
|
-
renderer.write(color.dim(" Goodbye!\n"));
|
|
464
|
-
return { mode: "tui-repl", cancelled: true };
|
|
465
|
-
}
|
|
466
|
-
const picked = MODE_OPTIONS.find((o) => String(o.key) === answer || o.mode === answer);
|
|
467
|
-
choice = picked ? { mode: picked.mode } : { mode: "tui-repl" };
|
|
468
|
-
}
|
|
469
|
-
if (bindsPort(choice.mode)) {
|
|
470
|
-
const port = await promptPort(deps, ports[choice.mode]);
|
|
471
|
-
choice.port = port;
|
|
472
|
-
const defaultHost = defaultHostFor(choice.mode);
|
|
473
|
-
const host = await promptHost(deps, defaultHost);
|
|
474
|
-
if (host !== defaultHost) choice.host = host;
|
|
475
|
-
}
|
|
476
|
-
return finalize(choice, ports);
|
|
477
|
-
}
|
|
478
|
-
function writeBanner(renderer) {
|
|
479
|
-
const columns = process.stdout.columns ?? 80;
|
|
480
|
-
renderer.write("\n");
|
|
481
|
-
for (const line of launchBannerLines(columns, CLI_VERSION)) {
|
|
482
|
-
renderer.write(` ${line}
|
|
483
|
-
`);
|
|
484
|
-
}
|
|
485
|
-
}
|
|
408
|
+
// src/boot/launch-menu-arrow.ts
|
|
486
409
|
function canUseArrowMenu() {
|
|
487
410
|
if (process.env.VITEST || process.env.NODE_ENV === "test") return false;
|
|
488
411
|
const stdin = process.stdin;
|
|
@@ -624,27 +547,119 @@ async function promptModeArrow(deps) {
|
|
|
624
547
|
}, 1e3);
|
|
625
548
|
});
|
|
626
549
|
}
|
|
550
|
+
|
|
551
|
+
// src/boot/launch-menu.ts
|
|
552
|
+
var DEFAULT_HOST = "127.0.0.1";
|
|
553
|
+
var HQ_DEFAULT_HOST = HQ_CLI_DEFAULT_HOST;
|
|
554
|
+
function bindsPort(mode) {
|
|
555
|
+
return mode !== "tui-repl" && mode !== "desktop";
|
|
556
|
+
}
|
|
557
|
+
function defaultHostFor(mode) {
|
|
558
|
+
return mode === "hq" ? HQ_DEFAULT_HOST : DEFAULT_HOST;
|
|
559
|
+
}
|
|
560
|
+
var SUMMARY_TIMEOUT_MS = 5e3;
|
|
561
|
+
var PORT_TIMEOUT_MS = 8e3;
|
|
562
|
+
function shouldSkipMenu(argv, flags, positional) {
|
|
563
|
+
if (flags["no-menu"] === true) return true;
|
|
564
|
+
if (flags["webui"] === true) return true;
|
|
565
|
+
if (flags["webui-session-child"] === true) return true;
|
|
566
|
+
if (flags["simpleui"] === true) return true;
|
|
567
|
+
if (flags["hq"] === true) return true;
|
|
568
|
+
if (flags["desktop"] === true) return true;
|
|
569
|
+
if (flags["no-interactive"] === true) return true;
|
|
570
|
+
if (flags["skip"] === true) return true;
|
|
571
|
+
if (typeof flags["prompt"] === "string") return true;
|
|
572
|
+
if (!isStdinTTY2()) return true;
|
|
573
|
+
if (positional.length > 0) return true;
|
|
574
|
+
void argv;
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
async function runLaunchMenu(deps) {
|
|
578
|
+
if (shouldSkipMenu(deps.argv, deps.flags, deps.positional)) {
|
|
579
|
+
return null;
|
|
580
|
+
}
|
|
581
|
+
const { renderer, reader, lastChoice } = deps;
|
|
582
|
+
const ports = { ...DEFAULT_PORTS, ...deps.defaultPorts ?? {} };
|
|
583
|
+
writeBanner(renderer);
|
|
584
|
+
if (lastChoice) {
|
|
585
|
+
const accept = await promptSummaryGate(deps);
|
|
586
|
+
if (accept === "use-last") {
|
|
587
|
+
return finalize(lastChoice, ports);
|
|
588
|
+
}
|
|
589
|
+
if (accept === "cancel") {
|
|
590
|
+
return { ...lastChoice, cancelled: true };
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
renderer.write(`
|
|
594
|
+
${color2.amber("?")} Choose how to run WrongStack:
|
|
595
|
+
|
|
596
|
+
`);
|
|
597
|
+
const arrowPick = await promptModeArrow(deps);
|
|
598
|
+
let choice;
|
|
599
|
+
if (arrowPick) {
|
|
600
|
+
if (arrowPick.cancelled) {
|
|
601
|
+
return { mode: "tui-repl", cancelled: true };
|
|
602
|
+
}
|
|
603
|
+
choice = { mode: arrowPick.mode };
|
|
604
|
+
} else {
|
|
605
|
+
for (const opt of MODE_OPTIONS) {
|
|
606
|
+
renderer.write(
|
|
607
|
+
` ${color2.bold(String(opt.key))}) ${opt.icon} ${color2.bold(opt.label)} ${color2.dim(opt.hint)}
|
|
608
|
+
`
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
renderer.write(`
|
|
612
|
+
${color2.dim("\u2500".repeat(48))}
|
|
613
|
+
`);
|
|
614
|
+
const answer = (await reader.readLine(
|
|
615
|
+
` ${color2.amber("?")} Mode ${color2.dim("[1-5, q to quit]")} ${color2.dim(`(auto 1 in ${MENU_TIMEOUT_MS / 1e3}s)`)} `,
|
|
616
|
+
{ timeoutMs: MENU_TIMEOUT_MS, defaultAnswer: "1" }
|
|
617
|
+
)).trim().toLowerCase();
|
|
618
|
+
if (answer === "q" || answer === "quit") {
|
|
619
|
+
renderer.write(color2.dim(" Goodbye!\n"));
|
|
620
|
+
return { mode: "tui-repl", cancelled: true };
|
|
621
|
+
}
|
|
622
|
+
const picked = MODE_OPTIONS.find((o) => String(o.key) === answer || o.mode === answer);
|
|
623
|
+
choice = picked ? { mode: picked.mode } : { mode: "tui-repl" };
|
|
624
|
+
}
|
|
625
|
+
if (bindsPort(choice.mode)) {
|
|
626
|
+
const port = await promptPort(deps, ports[choice.mode]);
|
|
627
|
+
choice.port = port;
|
|
628
|
+
const defaultHost = defaultHostFor(choice.mode);
|
|
629
|
+
const host = await promptHost(deps, defaultHost);
|
|
630
|
+
if (host !== defaultHost) choice.host = host;
|
|
631
|
+
}
|
|
632
|
+
return finalize(choice, ports);
|
|
633
|
+
}
|
|
634
|
+
function writeBanner(renderer) {
|
|
635
|
+
const columns = process.stdout.columns ?? 80;
|
|
636
|
+
renderer.write("\n");
|
|
637
|
+
for (const line of launchBannerLines(columns, CLI_VERSION)) {
|
|
638
|
+
renderer.write(` ${line}
|
|
639
|
+
`);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
627
642
|
async function promptSummaryGate(deps) {
|
|
628
643
|
const { renderer, reader, lastChoice } = deps;
|
|
629
644
|
if (!lastChoice) return "re-prompt";
|
|
630
645
|
const modeLabel = describeMode(lastChoice.mode);
|
|
631
|
-
const portStr = typeof lastChoice.port === "number" ? ` \xB7 port ${
|
|
632
|
-
const hostStr = typeof lastChoice.host === "string" ? ` \xB7 host ${
|
|
646
|
+
const portStr = typeof lastChoice.port === "number" ? ` \xB7 port ${color2.bold(String(lastChoice.port))}` : "";
|
|
647
|
+
const hostStr = typeof lastChoice.host === "string" ? ` \xB7 host ${color2.dim(lastChoice.host)}` : "";
|
|
633
648
|
renderer.write(`
|
|
634
|
-
${
|
|
649
|
+
${color2.dim("\u2500".repeat(48))}
|
|
635
650
|
`);
|
|
636
651
|
renderer.write(
|
|
637
|
-
` ${
|
|
652
|
+
` ${color2.cyan("\u23CE")} ${color2.dim("Last settings:")} ${color2.bold(modeLabel)}${portStr}${hostStr}
|
|
638
653
|
`
|
|
639
654
|
);
|
|
640
|
-
renderer.write(` ${
|
|
655
|
+
renderer.write(` ${color2.dim("\u2500".repeat(48))}
|
|
641
656
|
`);
|
|
642
657
|
const answer = (await reader.readLine(
|
|
643
|
-
` ${
|
|
658
|
+
` ${color2.amber("?")} Continue with these? ${color2.dim("[Y/n/q]")} ${color2.dim("(auto Y in 5s)")} `,
|
|
644
659
|
{ timeoutMs: SUMMARY_TIMEOUT_MS, defaultAnswer: "y" }
|
|
645
660
|
)).trim().toLowerCase();
|
|
646
661
|
if (answer === "q" || answer === "quit") {
|
|
647
|
-
renderer.write(
|
|
662
|
+
renderer.write(color2.dim(" Goodbye!\n"));
|
|
648
663
|
return "cancel";
|
|
649
664
|
}
|
|
650
665
|
if (answer === "n" || answer === "no") return "re-prompt";
|
|
@@ -655,7 +670,7 @@ async function promptPort(deps, defaultPort) {
|
|
|
655
670
|
const maxRetries = 3;
|
|
656
671
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
657
672
|
const answer = (await reader.readLine(
|
|
658
|
-
` ${
|
|
673
|
+
` ${color2.amber("?")} Port ${color2.dim(`[${defaultPort}]`)} ${color2.dim("(Enter = default, q = cancel)")} `,
|
|
659
674
|
{ timeoutMs: PORT_TIMEOUT_MS, defaultAnswer: "" }
|
|
660
675
|
)).trim();
|
|
661
676
|
if (answer === "" || answer === "\n") return defaultPort;
|
|
@@ -672,11 +687,11 @@ async function promptPort(deps, defaultPort) {
|
|
|
672
687
|
async function promptHost(deps, defaultHost) {
|
|
673
688
|
const { renderer, reader } = deps;
|
|
674
689
|
renderer.write(
|
|
675
|
-
` ${
|
|
690
|
+
` ${color2.dim("\u2139")} Press Enter to bind to ${color2.bold(defaultHost)}${defaultHost === HQ_DEFAULT_HOST ? " (all interfaces)" : " (loopback)"}.
|
|
676
691
|
`
|
|
677
692
|
);
|
|
678
693
|
const answer = (await reader.readLine(
|
|
679
|
-
` ${
|
|
694
|
+
` ${color2.amber("?")} Host ${color2.dim(`[${defaultHost}]`)} ${color2.dim("(Enter = default, q = cancel)")} `,
|
|
680
695
|
{ timeoutMs: PORT_TIMEOUT_MS, defaultAnswer: "" }
|
|
681
696
|
)).trim();
|
|
682
697
|
if (answer === "" || answer === "q" || answer === "quit") return defaultHost;
|
|
@@ -786,7 +801,7 @@ import { statSync } from "node:fs";
|
|
|
786
801
|
import { createRequire as createRequire3 } from "node:module";
|
|
787
802
|
import { homedir } from "node:os";
|
|
788
803
|
import * as path3 from "node:path";
|
|
789
|
-
import { color as
|
|
804
|
+
import { color as color3 } from "@wrongstack/core/utils";
|
|
790
805
|
function desktopExecutableCandidates(platform, home, env) {
|
|
791
806
|
const join7 = platform === "win32" ? path3.win32.join : path3.posix.join;
|
|
792
807
|
const managed = join7(home, ".wrongstack", "desktop");
|
|
@@ -862,7 +877,7 @@ async function launchDesktop(args) {
|
|
|
862
877
|
} catch {
|
|
863
878
|
process.stderr.write(
|
|
864
879
|
[
|
|
865
|
-
|
|
880
|
+
color3.red("\u2717 WrongStack Desktop is not installed."),
|
|
866
881
|
"",
|
|
867
882
|
"Download WrongStack Desktop from GitHub Releases:",
|
|
868
883
|
" https://github.com/WrongStack/WrongStack/releases/latest",
|
|
@@ -884,7 +899,7 @@ async function launchDesktop(args) {
|
|
|
884
899
|
});
|
|
885
900
|
child.once("error", (err) => {
|
|
886
901
|
process.stderr.write(
|
|
887
|
-
`${
|
|
902
|
+
`${color3.red("\u2717 Failed to start WrongStack Desktop:")} ${err.message}
|
|
888
903
|
`
|
|
889
904
|
);
|
|
890
905
|
resolve3(1);
|
|
@@ -904,7 +919,7 @@ import {
|
|
|
904
919
|
readHqRuntimeFileSync,
|
|
905
920
|
resolveHqDataDir
|
|
906
921
|
} from "@wrongstack/core/hq";
|
|
907
|
-
import { color as
|
|
922
|
+
import { color as color4, isPidAlive } from "@wrongstack/core/utils";
|
|
908
923
|
function isReusedContainerPid(markerPid, containerMode, currentPid = process.pid) {
|
|
909
924
|
return containerMode === "1" && markerPid === currentPid;
|
|
910
925
|
}
|
|
@@ -933,7 +948,7 @@ async function isPortInUse(host, port) {
|
|
|
933
948
|
}
|
|
934
949
|
async function handleHqShortCircuit(flags) {
|
|
935
950
|
if (flags["hq"] !== true) return null;
|
|
936
|
-
const { startHqServer } = await import("./hq-server-
|
|
951
|
+
const { startHqServer } = await import("./hq-server-YK7FBLL6.js");
|
|
937
952
|
const tunnelRequested = flags["tunnel"] === true;
|
|
938
953
|
const rawPublicUrl = typeof flags["hq-public-url"] === "string" ? flags["hq-public-url"] : process.env.WRONGSTACK_HQ_PUBLIC_URL;
|
|
939
954
|
let publicOrigin;
|
|
@@ -942,14 +957,14 @@ async function handleHqShortCircuit(flags) {
|
|
|
942
957
|
publicOrigin = normalizeHqPublicOrigin(rawPublicUrl);
|
|
943
958
|
} catch (cause) {
|
|
944
959
|
process.stderr.write(
|
|
945
|
-
`${
|
|
960
|
+
`${color4.red("\u2717")} ${cause instanceof Error ? cause.message : String(cause)}
|
|
946
961
|
`
|
|
947
962
|
);
|
|
948
963
|
return 1;
|
|
949
964
|
}
|
|
950
965
|
}
|
|
951
966
|
if (tunnelRequested && publicOrigin !== void 0) {
|
|
952
|
-
process.stderr.write(`${
|
|
967
|
+
process.stderr.write(`${color4.red("\u2717")} Use either --tunnel or --hq-public-url, not both.
|
|
953
968
|
`);
|
|
954
969
|
return 1;
|
|
955
970
|
}
|
|
@@ -957,7 +972,7 @@ async function handleHqShortCircuit(flags) {
|
|
|
957
972
|
const host = typeof flags["host"] === "string" ? flags["host"] : externallyPublished ? "127.0.0.1" : HQ_CLI_DEFAULT_HOST2;
|
|
958
973
|
if (externallyPublished && !isLoopbackHost(host)) {
|
|
959
974
|
process.stderr.write(
|
|
960
|
-
`${
|
|
975
|
+
`${color4.red("\u2717")} Public HQ publishing requires a loopback bind. Remove --host or use --host 127.0.0.1.
|
|
961
976
|
`
|
|
962
977
|
);
|
|
963
978
|
return 1;
|
|
@@ -969,7 +984,7 @@ async function handleHqShortCircuit(flags) {
|
|
|
969
984
|
if (Number.isFinite(parsed) && parsed > 0 && parsed < 65536) {
|
|
970
985
|
port = parsed;
|
|
971
986
|
} else {
|
|
972
|
-
process.stderr.write(`${
|
|
987
|
+
process.stderr.write(`${color4.red("\u2717")} Invalid --port value: ${flags["port"]}
|
|
973
988
|
`);
|
|
974
989
|
return 1;
|
|
975
990
|
}
|
|
@@ -982,7 +997,7 @@ async function handleHqShortCircuit(flags) {
|
|
|
982
997
|
});
|
|
983
998
|
} catch (cause) {
|
|
984
999
|
process.stderr.write(
|
|
985
|
-
`${
|
|
1000
|
+
`${color4.red("\u2717")} ${cause instanceof Error ? cause.message : String(cause)}
|
|
986
1001
|
`
|
|
987
1002
|
);
|
|
988
1003
|
return 1;
|
|
@@ -997,13 +1012,13 @@ async function handleHqShortCircuit(flags) {
|
|
|
997
1012
|
);
|
|
998
1013
|
} catch (cause) {
|
|
999
1014
|
process.stderr.write(
|
|
1000
|
-
`${
|
|
1015
|
+
`${color4.red("\u2717")} ${cause instanceof Error ? cause.message : String(cause)}
|
|
1001
1016
|
`
|
|
1002
1017
|
);
|
|
1003
1018
|
return 1;
|
|
1004
1019
|
}
|
|
1005
1020
|
if (password !== void 0 && password.length < 8) {
|
|
1006
|
-
process.stderr.write(`${
|
|
1021
|
+
process.stderr.write(`${color4.red("\u2717")} HQ password must be at least 8 characters.
|
|
1007
1022
|
`);
|
|
1008
1023
|
return 1;
|
|
1009
1024
|
}
|
|
@@ -1013,7 +1028,7 @@ async function handleHqShortCircuit(flags) {
|
|
|
1013
1028
|
const parsed = Number.parseInt(rawTrustedProxyHops, 10);
|
|
1014
1029
|
if (!Number.isFinite(parsed) || parsed < 0 || String(parsed) !== rawTrustedProxyHops.trim()) {
|
|
1015
1030
|
process.stderr.write(
|
|
1016
|
-
`${
|
|
1031
|
+
`${color4.red("\u2717")} --hq-trusted-proxy-hops must be a non-negative integer.
|
|
1017
1032
|
`
|
|
1018
1033
|
);
|
|
1019
1034
|
return 1;
|
|
@@ -1025,14 +1040,14 @@ async function handleHqShortCircuit(flags) {
|
|
|
1025
1040
|
const existing = await isHqAlreadyRunning(resolvedDataDir);
|
|
1026
1041
|
if (existing) {
|
|
1027
1042
|
process.stderr.write(
|
|
1028
|
-
`${
|
|
1043
|
+
`${color4.red("\u2717")} HQ is already running at ${existing.url} (PID ${existing.pid}). Stop it first or use a different --data-dir.
|
|
1029
1044
|
`
|
|
1030
1045
|
);
|
|
1031
1046
|
return 1;
|
|
1032
1047
|
}
|
|
1033
1048
|
if (await isPortInUse(host, port)) {
|
|
1034
1049
|
process.stderr.write(
|
|
1035
|
-
`${
|
|
1050
|
+
`${color4.red("\u2717")} Port ${port} is already in use. Choose a different port or stop the process using it.
|
|
1036
1051
|
`
|
|
1037
1052
|
);
|
|
1038
1053
|
return 1;
|
|
@@ -1043,7 +1058,7 @@ async function handleHqShortCircuit(flags) {
|
|
|
1043
1058
|
const { parseTokenTtlValue } = await import("./hq-ttl-RKRF7AQX.js");
|
|
1044
1059
|
const parsed = parseTokenTtlValue(rawTtl);
|
|
1045
1060
|
if (parsed.error) {
|
|
1046
|
-
process.stderr.write(`${
|
|
1061
|
+
process.stderr.write(`${color4.red("\u2717")} Invalid --hq-token-ttl: ${parsed.error}
|
|
1047
1062
|
`);
|
|
1048
1063
|
return 1;
|
|
1049
1064
|
}
|
|
@@ -1070,11 +1085,11 @@ async function handleHqShortCircuit(flags) {
|
|
|
1070
1085
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1071
1086
|
if (err instanceof Error && "code" in err && err.code === "EADDRINUSE") {
|
|
1072
1087
|
process.stderr.write(
|
|
1073
|
-
`${
|
|
1088
|
+
`${color4.red("\u2717")} Port ${port} is already in use. Please choose a different port.
|
|
1074
1089
|
`
|
|
1075
1090
|
);
|
|
1076
1091
|
} else {
|
|
1077
|
-
process.stderr.write(`${
|
|
1092
|
+
process.stderr.write(`${color4.red("\u2717")} Failed to start HQ server: ${msg}
|
|
1078
1093
|
`);
|
|
1079
1094
|
}
|
|
1080
1095
|
return 1;
|
|
@@ -1083,16 +1098,16 @@ async function handleHqShortCircuit(flags) {
|
|
|
1083
1098
|
if (handle.firstRunSetup?.passwordMode !== true) {
|
|
1084
1099
|
await handle.close();
|
|
1085
1100
|
process.stderr.write(
|
|
1086
|
-
`${
|
|
1101
|
+
`${color4.red("\u2717")} Persistent public HQ requires password mode. Set WRONGSTACK_HQ_PASSWORD and retry.
|
|
1087
1102
|
`
|
|
1088
1103
|
);
|
|
1089
1104
|
return 1;
|
|
1090
1105
|
}
|
|
1091
1106
|
handle.trustPublicOrigin(publicOrigin);
|
|
1092
1107
|
process.stdout.write(`
|
|
1093
|
-
${
|
|
1108
|
+
${color4.green("Persistent HQ origin ready:")} ${publicOrigin}/
|
|
1094
1109
|
`);
|
|
1095
|
-
process.stdout.write(`${
|
|
1110
|
+
process.stdout.write(`${color4.green("Mobile:")} ${publicOrigin}/mobile
|
|
1096
1111
|
`);
|
|
1097
1112
|
}
|
|
1098
1113
|
let tunnel;
|
|
@@ -1101,7 +1116,7 @@ ${color3.green("Persistent HQ origin ready:")} ${publicOrigin}/
|
|
|
1101
1116
|
if (handle.firstRunSetup !== void 0 && !handle.firstRunSetup.browserTokenMode && !handle.firstRunSetup.passwordMode) {
|
|
1102
1117
|
await handle.close();
|
|
1103
1118
|
process.stderr.write(
|
|
1104
|
-
`${
|
|
1119
|
+
`${color4.red("\u2717")} Refusing to publish HQ in open mode. Set --password or create a browser token first.
|
|
1105
1120
|
`
|
|
1106
1121
|
);
|
|
1107
1122
|
return 1;
|
|
@@ -1110,7 +1125,7 @@ ${color3.green("Persistent HQ origin ready:")} ${publicOrigin}/
|
|
|
1110
1125
|
const { buildPublicHqUrl, startHqQuickTunnel } = await import("./hq-tunnel-6VU4IWV4.js");
|
|
1111
1126
|
const originHost = handle.host === "::1" ? "[::1]" : handle.host;
|
|
1112
1127
|
tunnel = await startHqQuickTunnel(`http://${originHost}:${handle.port}`, {
|
|
1113
|
-
onUnexpectedExit: (message) => process.stderr.write(`${
|
|
1128
|
+
onUnexpectedExit: (message) => process.stderr.write(`${color4.yellow("!")} ${message}
|
|
1114
1129
|
`)
|
|
1115
1130
|
});
|
|
1116
1131
|
handle.trustPublicOrigin(new URL(tunnel.url).origin);
|
|
@@ -1120,22 +1135,22 @@ ${color3.green("Persistent HQ origin ready:")} ${publicOrigin}/
|
|
|
1120
1135
|
handle.firstRunSetup?.passwordMode !== true
|
|
1121
1136
|
);
|
|
1122
1137
|
process.stdout.write(`
|
|
1123
|
-
${
|
|
1138
|
+
${color4.green("Cloudflare Quick Tunnel ready:")} ${browserUrl}
|
|
1124
1139
|
`);
|
|
1125
1140
|
const tunnelMobileUrl = new URL(tunnel.url);
|
|
1126
1141
|
tunnelMobileUrl.pathname = "/mobile";
|
|
1127
1142
|
tunnelMobileUrl.search = "";
|
|
1128
1143
|
tunnelMobileUrl.hash = "";
|
|
1129
|
-
process.stdout.write(`${
|
|
1144
|
+
process.stdout.write(`${color4.green("Mobile:")} ${tunnelMobileUrl.toString()}
|
|
1130
1145
|
`);
|
|
1131
1146
|
process.stdout.write(
|
|
1132
|
-
`${
|
|
1147
|
+
`${color4.dim("Temporary development URL; DNS may need a few seconds, it changes on restart and ends when HQ stops.")}
|
|
1133
1148
|
`
|
|
1134
1149
|
);
|
|
1135
1150
|
} catch (err) {
|
|
1136
1151
|
await handle.close();
|
|
1137
1152
|
process.stderr.write(
|
|
1138
|
-
`${
|
|
1153
|
+
`${color4.red("\u2717")} Failed to start Cloudflare Quick Tunnel: ${err instanceof Error ? err.message : String(err)}
|
|
1139
1154
|
`
|
|
1140
1155
|
);
|
|
1141
1156
|
return 1;
|
|
@@ -1181,8 +1196,8 @@ import * as path9 from "node:path";
|
|
|
1181
1196
|
import { DefaultLogger } from "@wrongstack/core/infrastructure";
|
|
1182
1197
|
import { DefaultModelsRegistry, startCatalog } from "@wrongstack/core/models";
|
|
1183
1198
|
import {
|
|
1184
|
-
color as
|
|
1185
|
-
isStdinTTY as
|
|
1199
|
+
color as color14,
|
|
1200
|
+
isStdinTTY as isStdinTTY4,
|
|
1186
1201
|
toErrorMessage as toErrorMessage7,
|
|
1187
1202
|
writeErr as writeErr3
|
|
1188
1203
|
} from "@wrongstack/core/utils";
|
|
@@ -1215,7 +1230,7 @@ async function resolveAppendedSystemPrompt(flags, cwd) {
|
|
|
1215
1230
|
// src/boot/config-backup-recovery.ts
|
|
1216
1231
|
import * as fs3 from "node:fs/promises";
|
|
1217
1232
|
import * as path5 from "node:path";
|
|
1218
|
-
import { atomicWrite as atomicWrite2, backupConfigFile, color as
|
|
1233
|
+
import { atomicWrite as atomicWrite2, backupConfigFile, color as color5, toErrorMessage } from "@wrongstack/core/utils";
|
|
1219
1234
|
function isRecord(value) {
|
|
1220
1235
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1221
1236
|
}
|
|
@@ -1305,12 +1320,12 @@ async function maybeRestoreDefaultProfileFromBackup(opts) {
|
|
|
1305
1320
|
const providerSummary = remainder > 0 ? `${shownProviders} +${remainder}` : shownProviders;
|
|
1306
1321
|
opts.renderer.write(
|
|
1307
1322
|
`
|
|
1308
|
-
${
|
|
1309
|
-
${
|
|
1323
|
+
${color5.amber("\u25CB")} ${color5.bold(profileName)} profile has no saved providers.
|
|
1324
|
+
${color5.dim("Latest usable backup:")} ${color5.bold(backup.fileName)} ${color5.dim(`(${backup.providerIds.length} provider: ${providerSummary})`)}
|
|
1310
1325
|
`
|
|
1311
1326
|
);
|
|
1312
1327
|
const answer = (await opts.reader.readLine(
|
|
1313
|
-
` ${
|
|
1328
|
+
` ${color5.amber("?")} Restore all settings from this backup? ${color5.dim("[Y/n]")} `
|
|
1314
1329
|
)).trim().toLowerCase();
|
|
1315
1330
|
if (answer === "n" || answer === "no") return false;
|
|
1316
1331
|
try {
|
|
@@ -1320,7 +1335,7 @@ async function maybeRestoreDefaultProfileFromBackup(opts) {
|
|
|
1320
1335
|
profilePath: opts.profilePath
|
|
1321
1336
|
});
|
|
1322
1337
|
opts.renderer.write(
|
|
1323
|
-
` ${
|
|
1338
|
+
` ${color5.green("\u2713")} Restored all settings from ${color5.dim(backup.fileName)}
|
|
1324
1339
|
`
|
|
1325
1340
|
);
|
|
1326
1341
|
return true;
|
|
@@ -1357,7 +1372,7 @@ async function bootConfig(flags) {
|
|
|
1357
1372
|
}
|
|
1358
1373
|
|
|
1359
1374
|
// src/boot-launch-choices.ts
|
|
1360
|
-
import { color as
|
|
1375
|
+
import { color as color11, toErrorMessage as toErrorMessage5, writeErr } from "@wrongstack/core/utils";
|
|
1361
1376
|
|
|
1362
1377
|
// src/boot/system-prompt-menu.ts
|
|
1363
1378
|
import {
|
|
@@ -1367,11 +1382,11 @@ import {
|
|
|
1367
1382
|
SYSTEM_PROMPT_VARIANT_OPTIONS,
|
|
1368
1383
|
SYSTEM_PROMPT_VARIANTS
|
|
1369
1384
|
} from "@wrongstack/core/agent";
|
|
1370
|
-
import { color as
|
|
1385
|
+
import { color as color9 } from "@wrongstack/core/utils";
|
|
1371
1386
|
|
|
1372
1387
|
// src/pre-launch/first-run.ts
|
|
1373
1388
|
import { hasProviderCredential } from "@wrongstack/core/models";
|
|
1374
|
-
import { color as
|
|
1389
|
+
import { color as color6, toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
|
|
1375
1390
|
import { PROVIDER_DEFINITIONS } from "@wrongstack/providers/definitions";
|
|
1376
1391
|
async function hasAnyCredential(config, modelsRegistry, env = process.env) {
|
|
1377
1392
|
for (const cfg of Object.values(config.providers ?? {})) {
|
|
@@ -1397,39 +1412,39 @@ function renderWelcome(renderer) {
|
|
|
1397
1412
|
renderer.write(`${boxTop("Welcome to WrongStack")}
|
|
1398
1413
|
`);
|
|
1399
1414
|
renderer.write(
|
|
1400
|
-
`${boxRow(
|
|
1415
|
+
`${boxRow(color6.dim("No model is connected yet. Pick how you want to connect one:"))}
|
|
1401
1416
|
`
|
|
1402
1417
|
);
|
|
1403
1418
|
renderer.write(`${boxDivider()}
|
|
1404
1419
|
`);
|
|
1405
1420
|
renderer.write(
|
|
1406
1421
|
`${boxRow(
|
|
1407
|
-
`${theme.accent("1")} ${
|
|
1422
|
+
`${theme.accent("1")} ${color6.bold("Sign in with a subscription")} ${color6.dim("ChatGPT \xB7 Claude \xB7 GitHub Copilot")}`
|
|
1408
1423
|
)}
|
|
1409
1424
|
`
|
|
1410
1425
|
);
|
|
1411
1426
|
renderer.write(
|
|
1412
1427
|
`${boxRow(
|
|
1413
|
-
`${theme.accent("2")} ${
|
|
1428
|
+
`${theme.accent("2")} ${color6.bold("Add an API key")} ${color6.dim("Anthropic \xB7 OpenAI \xB7 Google \xB7 OpenRouter \xB7 \u2026")}`
|
|
1414
1429
|
)}
|
|
1415
1430
|
`
|
|
1416
1431
|
);
|
|
1417
1432
|
renderer.write(
|
|
1418
1433
|
`${boxRow(
|
|
1419
|
-
`${theme.accent("3")} ${
|
|
1434
|
+
`${theme.accent("3")} ${color6.bold("Use a local server")} ${color6.dim("Ollama \xB7 LM Studio \xB7 vLLM \xB7 OmniRoute")}`
|
|
1420
1435
|
)}
|
|
1421
1436
|
`
|
|
1422
1437
|
);
|
|
1423
1438
|
renderer.write(
|
|
1424
1439
|
`${boxRow(
|
|
1425
|
-
`${theme.accent("4")} ${
|
|
1440
|
+
`${theme.accent("4")} ${color6.bold("Continue without a key")} ${color6.dim("setup mode \u2014 explore the app, no model")}`
|
|
1426
1441
|
)}
|
|
1427
1442
|
`
|
|
1428
1443
|
);
|
|
1429
1444
|
renderer.write(`${boxDivider()}
|
|
1430
1445
|
`);
|
|
1431
1446
|
renderer.write(
|
|
1432
|
-
`${boxRow(
|
|
1447
|
+
`${boxRow(color6.dim("You can change this any time with /auth inside the app, or `wstack auth`."))}
|
|
1433
1448
|
`
|
|
1434
1449
|
);
|
|
1435
1450
|
renderer.write(`${boxBottom()}
|
|
@@ -1448,12 +1463,12 @@ async function runFirstRunSetup(deps) {
|
|
|
1448
1463
|
renderWelcome(renderer);
|
|
1449
1464
|
const answer = (await reader.readLine(
|
|
1450
1465
|
`
|
|
1451
|
-
${
|
|
1466
|
+
${color6.amber("?")} Choose ${color6.dim("(1-4)")} ${color6.dim("[q to quit]")}: `
|
|
1452
1467
|
)).trim().toLowerCase();
|
|
1453
1468
|
if (!answer || answer === "q" || answer === "quit" || answer === "exit") {
|
|
1454
1469
|
renderer.write(
|
|
1455
1470
|
`
|
|
1456
|
-
${
|
|
1471
|
+
${color6.dim("No provider configured. Run")} ${color6.bold("wstack auth")} ${color6.dim("when you are ready.")}
|
|
1457
1472
|
|
|
1458
1473
|
`
|
|
1459
1474
|
);
|
|
@@ -1490,7 +1505,7 @@ ${color5.amber("?")} Choose ${color5.dim("(1-4)")} ${color5.dim("[q to quit]")}:
|
|
|
1490
1505
|
|
|
1491
1506
|
// src/pre-launch/launch-prompts.ts
|
|
1492
1507
|
import * as fs4 from "node:fs/promises";
|
|
1493
|
-
import { atomicWrite as atomicWrite3, color as
|
|
1508
|
+
import { atomicWrite as atomicWrite3, color as color7, withFileLock as withFileLock2 } from "@wrongstack/core/utils";
|
|
1494
1509
|
var LaunchAbortedError = class extends Error {
|
|
1495
1510
|
exitCode = 0;
|
|
1496
1511
|
constructor() {
|
|
@@ -1521,19 +1536,19 @@ async function runLaunchPrompts(opts) {
|
|
|
1521
1536
|
yolo: yoloPinned ?? lastChoices.yolo,
|
|
1522
1537
|
autonomy: autonomyPinned ?? lastChoices.autonomy
|
|
1523
1538
|
};
|
|
1524
|
-
const onOff = (v) => v ?
|
|
1539
|
+
const onOff = (v) => v ? color7.green("on") : color7.dim("off");
|
|
1525
1540
|
const modeLabel = effective.mode.toUpperCase();
|
|
1526
1541
|
renderer.write(
|
|
1527
1542
|
`
|
|
1528
|
-
${
|
|
1543
|
+
${color7.dim("Last settings:")} ${color7.bold(modeLabel)} \xB7 YOLO ${onOff(effective.yolo)} \xB7 Autonomy ${effective.autonomy === "auto" ? color7.green("auto") : color7.dim("off")}
|
|
1529
1544
|
`
|
|
1530
1545
|
);
|
|
1531
1546
|
const answer = reuseLast ? "y" : (await reader.readLine(
|
|
1532
|
-
` ${
|
|
1547
|
+
` ${color7.amber("?")} Continue with these? ${color7.dim("[Y/n/q]")} ${color7.dim("(auto Y in 5s)")} `,
|
|
1533
1548
|
{ timeoutMs: 5e3, defaultAnswer: "y" }
|
|
1534
1549
|
)).trim().toLowerCase();
|
|
1535
1550
|
if (answer === "q") {
|
|
1536
|
-
renderer.write(
|
|
1551
|
+
renderer.write(color7.dim(" Goodbye!\n"));
|
|
1537
1552
|
throw new LaunchAbortedError();
|
|
1538
1553
|
}
|
|
1539
1554
|
if (answer !== "n" && answer !== "no") {
|
|
@@ -1541,7 +1556,7 @@ async function runLaunchPrompts(opts) {
|
|
|
1541
1556
|
const badgeStr2 = badges2.length > 0 ? ` (${badges2.join(" \xB7 ")})` : "";
|
|
1542
1557
|
renderer.write(
|
|
1543
1558
|
`
|
|
1544
|
-
${
|
|
1559
|
+
${color7.green("\u25B6")} Launching in ${color7.bold(modeLabel)} mode${badgeStr2}
|
|
1545
1560
|
|
|
1546
1561
|
`
|
|
1547
1562
|
);
|
|
@@ -1554,10 +1569,10 @@ async function runLaunchPrompts(opts) {
|
|
|
1554
1569
|
} else {
|
|
1555
1570
|
const answer = (await reader.readLine(
|
|
1556
1571
|
`
|
|
1557
|
-
${
|
|
1572
|
+
${color7.amber("?")} Interactive mode: ${color7.bold("T")}UI / ${color7.bold("R")}EPL ${color7.dim("[T/r/q]")} `
|
|
1558
1573
|
)).trim().toLowerCase();
|
|
1559
1574
|
if (answer === "q") {
|
|
1560
|
-
renderer.write(
|
|
1575
|
+
renderer.write(color7.dim(" Goodbye!\n"));
|
|
1561
1576
|
throw new LaunchAbortedError();
|
|
1562
1577
|
}
|
|
1563
1578
|
mode = answer === "r" || answer === "repl" ? "repl" : "tui";
|
|
@@ -1567,10 +1582,10 @@ async function runLaunchPrompts(opts) {
|
|
|
1567
1582
|
yolo = yoloPinned;
|
|
1568
1583
|
} else {
|
|
1569
1584
|
const answer = (await reader.readLine(
|
|
1570
|
-
` ${
|
|
1585
|
+
` ${color7.amber("?")} YOLO mode ${color7.dim("(auto-approve tool calls)")} ${color7.dim("[Y/n/q]")} `
|
|
1571
1586
|
)).trim().toLowerCase();
|
|
1572
1587
|
if (answer === "q") {
|
|
1573
|
-
renderer.write(
|
|
1588
|
+
renderer.write(color7.dim(" Goodbye!\n"));
|
|
1574
1589
|
throw new LaunchAbortedError();
|
|
1575
1590
|
}
|
|
1576
1591
|
yolo = answer !== "n" && answer !== "no";
|
|
@@ -1580,10 +1595,10 @@ async function runLaunchPrompts(opts) {
|
|
|
1580
1595
|
autonomy = autonomyPinned;
|
|
1581
1596
|
} else {
|
|
1582
1597
|
const answer = (await reader.readLine(
|
|
1583
|
-
` ${
|
|
1598
|
+
` ${color7.amber("?")} Autonomy mode ${color7.dim("(auto-continue \u2014 agent picks next step)")} ${color7.dim("[Y/n/q]")} `
|
|
1584
1599
|
)).trim().toLowerCase();
|
|
1585
1600
|
if (answer === "q") {
|
|
1586
|
-
renderer.write(
|
|
1601
|
+
renderer.write(color7.dim(" Goodbye!\n"));
|
|
1587
1602
|
throw new LaunchAbortedError();
|
|
1588
1603
|
}
|
|
1589
1604
|
autonomy = answer !== "n" && answer !== "no" ? "auto" : "off";
|
|
@@ -1592,7 +1607,7 @@ async function runLaunchPrompts(opts) {
|
|
|
1592
1607
|
const badgeStr = badges.length > 0 ? ` (${badges.join(" \xB7 ")})` : "";
|
|
1593
1608
|
renderer.write(
|
|
1594
1609
|
`
|
|
1595
|
-
${
|
|
1610
|
+
${color7.green("\u25B6")} Launching in ${color7.bold(mode.toUpperCase())} mode${badgeStr}
|
|
1596
1611
|
|
|
1597
1612
|
`
|
|
1598
1613
|
);
|
|
@@ -1600,20 +1615,20 @@ async function runLaunchPrompts(opts) {
|
|
|
1600
1615
|
}
|
|
1601
1616
|
function buildBadges(chosen) {
|
|
1602
1617
|
const badges = [];
|
|
1603
|
-
if (chosen.yolo) badges.push(
|
|
1618
|
+
if (chosen.yolo) badges.push(color7.yellow("YOLO"));
|
|
1604
1619
|
if (chosen.autonomy !== "off")
|
|
1605
|
-
badges.push(
|
|
1620
|
+
badges.push(color7.magenta(`AUTONOMY:${chosen.autonomy.toUpperCase()}`));
|
|
1606
1621
|
return badges;
|
|
1607
1622
|
}
|
|
1608
1623
|
async function promptStopAskingStartupQuestions(opts) {
|
|
1609
1624
|
const answer = (await opts.reader.readLine(
|
|
1610
|
-
` ${
|
|
1625
|
+
` ${color7.amber("?")} Stop asking these startup questions? ${color7.dim("(reuse the last choices from now on)")} ${color7.dim("[y/N]")} ${color7.dim("(auto N in 5s)")} `,
|
|
1611
1626
|
{ timeoutMs: 5e3, defaultAnswer: "n" }
|
|
1612
1627
|
)).trim().toLowerCase();
|
|
1613
1628
|
const stop = answer === "y" || answer === "yes";
|
|
1614
1629
|
if (stop) {
|
|
1615
1630
|
opts.renderer.write(
|
|
1616
|
-
` ${
|
|
1631
|
+
` ${color7.green("\u25B6")} ${color7.dim("Startup questions off \u2014 turn back on with /settings reuse-startup-choices off.")}
|
|
1617
1632
|
|
|
1618
1633
|
`
|
|
1619
1634
|
);
|
|
@@ -1657,7 +1672,7 @@ async function persistLaunchChoices(configPath, choices, extra) {
|
|
|
1657
1672
|
import * as fs5 from "node:fs/promises";
|
|
1658
1673
|
import * as path6 from "node:path";
|
|
1659
1674
|
import {
|
|
1660
|
-
color as
|
|
1675
|
+
color as color8,
|
|
1661
1676
|
detectProjectKind,
|
|
1662
1677
|
isOutsideProject,
|
|
1663
1678
|
toErrorMessage as toErrorMessage3
|
|
@@ -1677,7 +1692,7 @@ async function runProjectCheck(opts) {
|
|
|
1677
1692
|
if (kind === "initialized") {
|
|
1678
1693
|
renderer.write(
|
|
1679
1694
|
`
|
|
1680
|
-
${
|
|
1695
|
+
${color8.green("\u2713")} Project initialized ${color8.dim(`(${path6.join(projectRoot, ".wrongstack", "AGENTS.md")})`)}
|
|
1681
1696
|
`
|
|
1682
1697
|
);
|
|
1683
1698
|
return true;
|
|
@@ -1685,20 +1700,20 @@ async function runProjectCheck(opts) {
|
|
|
1685
1700
|
if (kind === "project") {
|
|
1686
1701
|
renderer.write(
|
|
1687
1702
|
`
|
|
1688
|
-
${
|
|
1703
|
+
${color8.amber("\u25CF")} Project detected ${color8.dim(`(${projectRoot})`)} but ${color8.bold(".wrongstack/AGENTS.md")} is missing.
|
|
1689
1704
|
`
|
|
1690
1705
|
);
|
|
1691
1706
|
const answer2 = (await reader.readLine(
|
|
1692
|
-
` ${
|
|
1707
|
+
` ${color8.amber("?")} Scaffold ${color8.bold("AGENTS.md")} now? ${color8.dim("[y/N/q]")} `
|
|
1693
1708
|
)).trim().toLowerCase();
|
|
1694
1709
|
if (answer2 === "q") {
|
|
1695
|
-
renderer.write(
|
|
1710
|
+
renderer.write(color8.dim(" Cancelled.\n"));
|
|
1696
1711
|
return false;
|
|
1697
1712
|
}
|
|
1698
1713
|
if (answer2 === "y" || answer2 === "yes") {
|
|
1699
1714
|
try {
|
|
1700
1715
|
const file = await scaffoldAgentsMd(projectRoot);
|
|
1701
|
-
renderer.write(` ${
|
|
1716
|
+
renderer.write(` ${color8.green("\u2713")} Wrote ${color8.dim(file)}
|
|
1702
1717
|
`);
|
|
1703
1718
|
} catch (err) {
|
|
1704
1719
|
renderer.writeError(`Failed to scaffold AGENTS.md: ${toErrorMessage3(err)}`);
|
|
@@ -1716,14 +1731,14 @@ async function runProjectCheck(opts) {
|
|
|
1716
1731
|
if (!hasGit) {
|
|
1717
1732
|
renderer.write(
|
|
1718
1733
|
`
|
|
1719
|
-
${
|
|
1734
|
+
${color8.dim("\u25CB")} ${color8.dim(`No project manifest in ${projectRoot} \u2014 running in a scratch directory.`)}
|
|
1720
1735
|
`
|
|
1721
1736
|
);
|
|
1722
1737
|
const answer2 = (await reader.readLine(
|
|
1723
|
-
` ${
|
|
1738
|
+
` ${color8.amber("?")} No git repo found. ${color8.bold("Initialize git?")} ${color8.dim("[y/N/q]")} `
|
|
1724
1739
|
)).trim().toLowerCase();
|
|
1725
1740
|
if (answer2 === "q") {
|
|
1726
|
-
renderer.write(
|
|
1741
|
+
renderer.write(color8.dim(" Cancelled.\n"));
|
|
1727
1742
|
return false;
|
|
1728
1743
|
}
|
|
1729
1744
|
if (answer2 === "y" || answer2 === "yes") {
|
|
@@ -1741,7 +1756,7 @@ async function runProjectCheck(opts) {
|
|
|
1741
1756
|
(code) => code === 0 ? resolve3() : reject(new Error(`git init failed with ${code}`))
|
|
1742
1757
|
);
|
|
1743
1758
|
});
|
|
1744
|
-
renderer.write(` ${
|
|
1759
|
+
renderer.write(` ${color8.green("\u2713")} Git repository initialized
|
|
1745
1760
|
`);
|
|
1746
1761
|
} catch (err) {
|
|
1747
1762
|
renderer.writeError(`git init failed: ${toErrorMessage3(err)}
|
|
@@ -1751,13 +1766,13 @@ async function runProjectCheck(opts) {
|
|
|
1751
1766
|
} else {
|
|
1752
1767
|
renderer.write(
|
|
1753
1768
|
`
|
|
1754
|
-
${
|
|
1769
|
+
${color8.dim("\u25CB")} ${color8.dim(`No project manifest in ${projectRoot} \u2014 running in a scratch directory.`)}
|
|
1755
1770
|
`
|
|
1756
1771
|
);
|
|
1757
1772
|
}
|
|
1758
|
-
const answer = (await reader.readLine(` ${
|
|
1773
|
+
const answer = (await reader.readLine(` ${color8.amber("?")} Continue anyway? ${color8.dim("[Y/n/q]")} `)).trim().toLowerCase();
|
|
1759
1774
|
if (answer === "q" || answer === "n" || answer === "no") {
|
|
1760
|
-
renderer.write(
|
|
1775
|
+
renderer.write(color8.dim(" Cancelled.\n"));
|
|
1761
1776
|
return false;
|
|
1762
1777
|
}
|
|
1763
1778
|
return true;
|
|
@@ -1790,7 +1805,7 @@ async function runSystemPromptMenu(deps) {
|
|
|
1790
1805
|
const { renderer, reader, paths, lastVariant, suggestScout, reuseLast } = deps;
|
|
1791
1806
|
if (lastVariant && reuseLast) {
|
|
1792
1807
|
renderer.write(
|
|
1793
|
-
` ${
|
|
1808
|
+
` ${color9.green("\u25B6")} ${color9.bold(labelFor(lastVariant))} ${color9.dim("system prompt")}
|
|
1794
1809
|
`
|
|
1795
1810
|
);
|
|
1796
1811
|
return lastVariant;
|
|
@@ -1801,39 +1816,39 @@ async function runSystemPromptMenu(deps) {
|
|
|
1801
1816
|
if (suggestScout && lastVariant !== "scout") {
|
|
1802
1817
|
renderer.write(
|
|
1803
1818
|
`
|
|
1804
|
-
${
|
|
1819
|
+
${color9.dim("\u25CB")} ${color9.dim(`Not a project folder \u2014 ${labelFor("scout")} (general-purpose) may fit better; answer n to choose it.`)}
|
|
1805
1820
|
`
|
|
1806
1821
|
);
|
|
1807
1822
|
}
|
|
1808
1823
|
const answer2 = (await reader.readLine(
|
|
1809
|
-
` ${
|
|
1824
|
+
` ${color9.amber("?")} Continue with ${color9.bold(labelFor(lastVariant))} system prompt ${color9.dim(`(~${fmtTok(tokens[lastVariant])} tokens)`)}? ${color9.dim("[Y/n/q]")} ${color9.dim("(auto Y in 5s)")} `,
|
|
1810
1825
|
{ timeoutMs: SUMMARY_TIMEOUT_MS2, defaultAnswer: "y" }
|
|
1811
1826
|
)).trim().toLowerCase();
|
|
1812
1827
|
if (answer2 === "q" || answer2 === "quit") throw new LaunchAbortedError();
|
|
1813
1828
|
if (answer2 !== "n" && answer2 !== "no") return lastVariant;
|
|
1814
1829
|
}
|
|
1815
1830
|
renderer.write(`
|
|
1816
|
-
${
|
|
1831
|
+
${color9.amber("?")} System prompt:
|
|
1817
1832
|
`);
|
|
1818
1833
|
if (suggestScout) {
|
|
1819
1834
|
renderer.write(
|
|
1820
|
-
` ${
|
|
1835
|
+
` ${color9.dim(`Not a project folder \u2014 ${labelFor("scout")} is preselected.`)}
|
|
1821
1836
|
`
|
|
1822
1837
|
);
|
|
1823
1838
|
}
|
|
1824
1839
|
for (const [index, opt] of SYSTEM_PROMPT_OPTIONS.entries()) {
|
|
1825
1840
|
const num2 = index + 1;
|
|
1826
1841
|
const isDefault = opt.variant === defaultVariant;
|
|
1827
|
-
const marker = isDefault ?
|
|
1828
|
-
const label = isDefault ?
|
|
1842
|
+
const marker = isDefault ? color9.cyan("\u25CF") : color9.dim("\u25CB");
|
|
1843
|
+
const label = isDefault ? color9.bold(opt.label) : opt.label;
|
|
1829
1844
|
renderer.write(
|
|
1830
|
-
` ${
|
|
1845
|
+
` ${color9.dim(`${num2}.`)} ${marker} ${label.padEnd(9)} ${color9.dim(`~${fmtTok(tokens[opt.variant])} tokens`)} ${color9.dim(opt.hint)}
|
|
1831
1846
|
`
|
|
1832
1847
|
);
|
|
1833
1848
|
}
|
|
1834
1849
|
const answer = (await reader.readLine(
|
|
1835
1850
|
`
|
|
1836
|
-
${
|
|
1851
|
+
${color9.amber("?")} Select system prompt ${color9.dim(`[1-${SYSTEM_PROMPT_OPTIONS.length}, Enter = ${labelFor(defaultVariant)}, q to quit]`)}: `
|
|
1837
1852
|
)).trim().toLowerCase();
|
|
1838
1853
|
if (answer === "q" || answer === "quit") throw new LaunchAbortedError();
|
|
1839
1854
|
if (!answer) return defaultVariant;
|
|
@@ -1864,7 +1879,7 @@ async function maybeRunSystemPromptMenu(opts) {
|
|
|
1864
1879
|
if (chosen === savedVariant) return { variant: chosen, aborted: false, changed: false };
|
|
1865
1880
|
if (opts.outsideProject && chosen === "scout") {
|
|
1866
1881
|
opts.renderer.write(
|
|
1867
|
-
` ${
|
|
1882
|
+
` ${color9.dim(`${labelFor("scout")} for this launch only; the saved default stays ${labelFor(savedVariant ?? "default")}.`)}
|
|
1868
1883
|
`
|
|
1869
1884
|
);
|
|
1870
1885
|
return { variant: chosen, aborted: false, changed: true };
|
|
@@ -1887,7 +1902,7 @@ import { createRequire as createRequire4 } from "node:module";
|
|
|
1887
1902
|
import * as path7 from "node:path";
|
|
1888
1903
|
import { fileURLToPath } from "node:url";
|
|
1889
1904
|
import {
|
|
1890
|
-
color as
|
|
1905
|
+
color as color10,
|
|
1891
1906
|
moduleUrlFor,
|
|
1892
1907
|
toErrorMessage as toErrorMessage4,
|
|
1893
1908
|
wrongstackPackageJsonPath as wrongstackPackageJsonPath3
|
|
@@ -1907,6 +1922,8 @@ async function validateSavedProviderModel(config, modelsRegistry) {
|
|
|
1907
1922
|
const modelId = config.model;
|
|
1908
1923
|
if (!providerId || !modelId) return { ok: false, reason: "missing provider/model" };
|
|
1909
1924
|
if (isSetupProvider(providerId)) return { ok: true };
|
|
1925
|
+
if (providerId === ACP_LEADER_PROVIDER_ID) return { ok: true };
|
|
1926
|
+
if (providerId === WRONGFORGE_AGENT_ID) return { ok: true };
|
|
1910
1927
|
const saved = config.providers?.[providerId];
|
|
1911
1928
|
const lookupId = saved?.type && saved.type !== providerId ? saved.type : providerId;
|
|
1912
1929
|
const catalogProvider = await modelsRegistry.getProvider(lookupId).catch(() => void 0);
|
|
@@ -1989,10 +2006,10 @@ async function checkGitInCwd(opts) {
|
|
|
1989
2006
|
if (!hasCwdGit) {
|
|
1990
2007
|
renderer.write(
|
|
1991
2008
|
`
|
|
1992
|
-
${
|
|
2009
|
+
${color10.amber("\u25CB")} This folder has no ${color10.bold(".git")} repository.
|
|
1993
2010
|
`
|
|
1994
2011
|
);
|
|
1995
|
-
const answer = (await reader.readLine(` ${
|
|
2012
|
+
const answer = (await reader.readLine(` ${color10.amber("?")} Initialize one here? ${color10.dim("[y/N]")} `)).trim().toLowerCase();
|
|
1996
2013
|
if (answer === "y" || answer === "yes") {
|
|
1997
2014
|
try {
|
|
1998
2015
|
const { spawn: spawn2 } = await import("node:child_process");
|
|
@@ -2008,7 +2025,7 @@ async function checkGitInCwd(opts) {
|
|
|
2008
2025
|
(code) => code === 0 ? resolve3() : reject(new Error(`git init failed with ${code}`))
|
|
2009
2026
|
);
|
|
2010
2027
|
});
|
|
2011
|
-
renderer.write(` ${
|
|
2028
|
+
renderer.write(` ${color10.green("\u2713")} Git repository initialized
|
|
2012
2029
|
`);
|
|
2013
2030
|
hasCwdGit = true;
|
|
2014
2031
|
} catch (err) {
|
|
@@ -2022,7 +2039,7 @@ async function checkGitInCwd(opts) {
|
|
|
2022
2039
|
try {
|
|
2023
2040
|
await fs6.access(path7.join(parentDir, ".git"));
|
|
2024
2041
|
renderer.write(
|
|
2025
|
-
` ${
|
|
2042
|
+
` ${color10.dim("\u2139")} A ${color10.bold(".git")} repo exists in the parent directory: ${color10.dim(parentDir)}
|
|
2026
2043
|
`
|
|
2027
2044
|
);
|
|
2028
2045
|
} catch {
|
|
@@ -2120,8 +2137,8 @@ async function applyBootLaunchChoices(input) {
|
|
|
2120
2137
|
if (shouldPrintYoloNotice(lastChoices, yoloPinned, choices.yolo)) {
|
|
2121
2138
|
writeErr(
|
|
2122
2139
|
`
|
|
2123
|
-
${
|
|
2124
|
-
${
|
|
2140
|
+
${color11.yellow("YOLO is on")}: non-denied tool calls, including shell and file writes, run without confirmation.
|
|
2141
|
+
${color11.dim("Damaging calls and calls your deny rules forbid still ask. Use")} --no-yolo ${color11.dim("or")} /yolo off ${color11.dim("to require prompts.")}
|
|
2125
2142
|
|
|
2126
2143
|
`
|
|
2127
2144
|
);
|
|
@@ -2132,7 +2149,7 @@ async function applyBootLaunchChoices(input) {
|
|
|
2132
2149
|
});
|
|
2133
2150
|
}
|
|
2134
2151
|
if (reuseLast && lastChoices) {
|
|
2135
|
-
renderer.write(` ${
|
|
2152
|
+
renderer.write(` ${color11.dim(REUSE_STARTUP_CHOICES_HINT)}
|
|
2136
2153
|
|
|
2137
2154
|
`);
|
|
2138
2155
|
}
|
|
@@ -2174,7 +2191,7 @@ async function applyBootLaunchChoices(input) {
|
|
|
2174
2191
|
}
|
|
2175
2192
|
|
|
2176
2193
|
// src/boot-provider-gate.ts
|
|
2177
|
-
import { color as
|
|
2194
|
+
import { color as color12, isStdinTTY as isStdinTTY3, toErrorMessage as toErrorMessage6, writeErr as writeErr2 } from "@wrongstack/core/utils";
|
|
2178
2195
|
import { isSetupProvider as isSetupProvider2, SETUP_MODEL_ID, SETUP_PROVIDER_ID } from "@wrongstack/providers";
|
|
2179
2196
|
async function resolveBootProviderModel(input) {
|
|
2180
2197
|
let { config, vault } = input;
|
|
@@ -2190,14 +2207,14 @@ async function resolveBootProviderModel(input) {
|
|
|
2190
2207
|
}
|
|
2191
2208
|
}
|
|
2192
2209
|
if (!(!!providerFlag && !!modelFlag)) {
|
|
2193
|
-
if (
|
|
2210
|
+
if (isStdinTTY3() && !noInteractiveMode) {
|
|
2194
2211
|
let picked;
|
|
2195
2212
|
let skipPicker = false;
|
|
2196
2213
|
if (isSetupProvider2(config.provider)) {
|
|
2197
2214
|
skipPicker = true;
|
|
2198
2215
|
renderer.write(
|
|
2199
2216
|
`
|
|
2200
|
-
${
|
|
2217
|
+
${color12.amber("\u25B6")} ${color12.bold("Setup mode")} ${color12.dim("\u2014 no model connected. Run")} ${color12.bold("/auth")} ${color12.dim("to connect one.")}
|
|
2201
2218
|
|
|
2202
2219
|
`
|
|
2203
2220
|
);
|
|
@@ -2237,7 +2254,7 @@ async function resolveBootProviderModel(input) {
|
|
|
2237
2254
|
const savedStatus = await validateSavedProviderModel(config, modelsRegistry);
|
|
2238
2255
|
renderer.write(
|
|
2239
2256
|
`
|
|
2240
|
-
${
|
|
2257
|
+
${color12.dim("Last settings:")} ${color12.bold(savedProvider)} / ${color12.bold(savedModel)}
|
|
2241
2258
|
`
|
|
2242
2259
|
);
|
|
2243
2260
|
if (!savedStatus.ok) {
|
|
@@ -2249,17 +2266,17 @@ async function resolveBootProviderModel(input) {
|
|
|
2249
2266
|
skipPicker = true;
|
|
2250
2267
|
renderer.write(
|
|
2251
2268
|
`
|
|
2252
|
-
${
|
|
2269
|
+
${color12.green("\u25B6")} ${color12.bold(savedProvider)} / ${color12.bold(savedModel)}
|
|
2253
2270
|
|
|
2254
2271
|
`
|
|
2255
2272
|
);
|
|
2256
2273
|
} else {
|
|
2257
2274
|
const answer = (await reader.readLine(
|
|
2258
|
-
` ${
|
|
2275
|
+
` ${color12.amber("?")} Continue with these? ${color12.dim("[Y/n/q]")} ${color12.dim("(auto Y in 5s)")} `,
|
|
2259
2276
|
{ timeoutMs: 5e3, defaultAnswer: "y" }
|
|
2260
2277
|
)).trim().toLowerCase();
|
|
2261
2278
|
if (answer === "q") {
|
|
2262
|
-
renderer.write(
|
|
2279
|
+
renderer.write(color12.dim(" Goodbye!\n"));
|
|
2263
2280
|
await reader.close();
|
|
2264
2281
|
return { kind: "exit", code: 0 };
|
|
2265
2282
|
}
|
|
@@ -2267,7 +2284,7 @@ async function resolveBootProviderModel(input) {
|
|
|
2267
2284
|
skipPicker = true;
|
|
2268
2285
|
renderer.write(
|
|
2269
2286
|
`
|
|
2270
|
-
${
|
|
2287
|
+
${color12.green("\u25B6")} ${color12.bold(savedProvider)} / ${color12.bold(savedModel)}
|
|
2271
2288
|
|
|
2272
2289
|
`
|
|
2273
2290
|
);
|
|
@@ -2288,9 +2305,9 @@ async function resolveBootProviderModel(input) {
|
|
|
2288
2305
|
if (!config.provider || !config.model) {
|
|
2289
2306
|
renderer.write(
|
|
2290
2307
|
`
|
|
2291
|
-
${
|
|
2292
|
-
${
|
|
2293
|
-
${
|
|
2308
|
+
${color12.dim("No provider selected.")}
|
|
2309
|
+
${color12.dim("Run")} ${color12.bold("wstack auth")} ${color12.dim("to add a key or sign in, or start with no model:")}
|
|
2310
|
+
${color12.bold(`wstack --provider ${SETUP_PROVIDER_ID} --model ${SETUP_MODEL_ID}`)}
|
|
2294
2311
|
|
|
2295
2312
|
`
|
|
2296
2313
|
);
|
|
@@ -2731,7 +2748,7 @@ function dim(s) {
|
|
|
2731
2748
|
}
|
|
2732
2749
|
|
|
2733
2750
|
// src/renderer.ts
|
|
2734
|
-
import { color as
|
|
2751
|
+
import { color as color13, sanitizeTerminalText } from "@wrongstack/core/utils";
|
|
2735
2752
|
var TerminalRenderer = class _TerminalRenderer {
|
|
2736
2753
|
out;
|
|
2737
2754
|
err;
|
|
@@ -2845,7 +2862,7 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2845
2862
|
const arrow = theme2.primary("\u2192");
|
|
2846
2863
|
const display = sanitizeTerminalText(formatInputSummary(input));
|
|
2847
2864
|
this.out.write(
|
|
2848
|
-
`${arrow} ${theme2.bold(sanitizeTerminalText(name))}${display ?
|
|
2865
|
+
`${arrow} ${theme2.bold(sanitizeTerminalText(name))}${display ? color13.dim(` ${display}`) : ""}
|
|
2849
2866
|
`
|
|
2850
2867
|
);
|
|
2851
2868
|
this.lineStart = true;
|
|
@@ -2865,7 +2882,7 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2865
2882
|
if (isError) {
|
|
2866
2883
|
const firstLine = txt.split("\n")[0] ?? "";
|
|
2867
2884
|
const truncated = firstLine.length > 200 ? `${firstLine.slice(0, 197)}\u2026` : firstLine;
|
|
2868
|
-
this.out.write(` ${prefix} ${
|
|
2885
|
+
this.out.write(` ${prefix} ${color13.dim(truncated)}
|
|
2869
2886
|
`);
|
|
2870
2887
|
this.lineStart = true;
|
|
2871
2888
|
return;
|
|
@@ -2873,7 +2890,7 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2873
2890
|
const isEditLike = name === "edit" || name === "write";
|
|
2874
2891
|
const diff = extractDiff(content);
|
|
2875
2892
|
if (isEditLike && diff) {
|
|
2876
|
-
this.out.write(` ${prefix} ${
|
|
2893
|
+
this.out.write(` ${prefix} ${color13.dim(sanitizeTerminalText(summarize(content, name)))}
|
|
2877
2894
|
`);
|
|
2878
2895
|
const rendered = renderDiff(diff).split("\n").map((l) => ` ${l}`).join("\n");
|
|
2879
2896
|
this.out.write(`${rendered}
|
|
@@ -2884,7 +2901,7 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2884
2901
|
const summary = sanitizeTerminalText(summarize(content, name));
|
|
2885
2902
|
const isReadLike = name === "read" || name === "grep" || name === "glob" || name === "bash" || name === "exec";
|
|
2886
2903
|
if (renderMode === "simple") {
|
|
2887
|
-
this.out.write(` ${prefix} ${
|
|
2904
|
+
this.out.write(` ${prefix} ${color13.dim(summary || compactSingleLine(bodyText))}
|
|
2888
2905
|
`);
|
|
2889
2906
|
this.lineStart = true;
|
|
2890
2907
|
return;
|
|
@@ -2893,16 +2910,16 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2893
2910
|
const lines = bodyText.split("\n");
|
|
2894
2911
|
const head = lines.slice(0, previewLines).map((l) => l.replace(/\s+$/, ""));
|
|
2895
2912
|
const moreCount = Math.max(0, lines.length - head.length);
|
|
2896
|
-
this.out.write(` ${prefix} ${
|
|
2913
|
+
this.out.write(` ${prefix} ${color13.dim(summary)}
|
|
2897
2914
|
`);
|
|
2898
2915
|
for (const l of head) {
|
|
2899
2916
|
const capped = l.length > 200 ? `${l.slice(0, 197)}\u2026` : l;
|
|
2900
|
-
this.out.write(` ${
|
|
2917
|
+
this.out.write(` ${color13.dim(capped)}
|
|
2901
2918
|
`);
|
|
2902
2919
|
}
|
|
2903
2920
|
if (moreCount > 0) {
|
|
2904
2921
|
this.out.write(
|
|
2905
|
-
` ${
|
|
2922
|
+
` ${color13.dim(`+${moreCount} more line${moreCount === 1 ? "" : "s"}`)}
|
|
2906
2923
|
`
|
|
2907
2924
|
);
|
|
2908
2925
|
}
|
|
@@ -3041,7 +3058,7 @@ function renderMarkdown(s) {
|
|
|
3041
3058
|
return theme2.primary(theme2.bold(`${hashes} ${text}`));
|
|
3042
3059
|
});
|
|
3043
3060
|
out = out.replace(/```([a-zA-Z0-9_+-]*)\n([\s\S]*?)```/g, (_m, _lang, code) => {
|
|
3044
|
-
return
|
|
3061
|
+
return color13.gray(`
|
|
3045
3062
|
\u250C\u2500
|
|
3046
3063
|
${code.replace(/^/gm, "\u2502 ")}\u2514\u2500`);
|
|
3047
3064
|
});
|
|
@@ -3049,7 +3066,7 @@ ${code.replace(/^/gm, "\u2502 ")}\u2514\u2500`);
|
|
|
3049
3066
|
out = out.replace(/\*\*([^*]+)\*\*/g, (_m, text) => theme2.bold(text));
|
|
3050
3067
|
out = out.replace(
|
|
3051
3068
|
/(^|[^*])\*([^*\n]+)\*([^*]|$)/g,
|
|
3052
|
-
(_m, l, t, r) => `${l}${
|
|
3069
|
+
(_m, l, t, r) => `${l}${color13.italic(t)}${r}`
|
|
3053
3070
|
);
|
|
3054
3071
|
return out;
|
|
3055
3072
|
}
|
|
@@ -3277,7 +3294,7 @@ async function boot(argv) {
|
|
|
3277
3294
|
return 2;
|
|
3278
3295
|
}
|
|
3279
3296
|
let first = positional[0];
|
|
3280
|
-
const mayOfferConfigRecovery =
|
|
3297
|
+
const mayOfferConfigRecovery = isStdinTTY4() && (positional.length === 0 || first === "quick") && typeof flags["prompt"] !== "string" && !flags["webui"] && !flags["no-interactive"] && !flags["skip"];
|
|
3281
3298
|
const machineOutput = flags["output-json"] === true || flags["output-format"] === "json" || flags["output-format"] === "stream-json";
|
|
3282
3299
|
const renderer = new TerminalRenderer(machineOutput ? { out: process.stderr } : void 0);
|
|
3283
3300
|
const reader = new ReadlineInputReader({ historyFile: paths.wpaths.historyFile });
|
|
@@ -3366,8 +3383,8 @@ async function boot(argv) {
|
|
|
3366
3383
|
if (isHomeDirectory(cwd, userHome)) {
|
|
3367
3384
|
writeErr3(
|
|
3368
3385
|
`
|
|
3369
|
-
${
|
|
3370
|
-
${
|
|
3386
|
+
${color14.red(color14.bold("\u26A0 This is not a working directory."))}
|
|
3387
|
+
${color14.red("Please open wstack in a project folder.")}
|
|
3371
3388
|
|
|
3372
3389
|
`
|
|
3373
3390
|
);
|
|
@@ -3392,7 +3409,7 @@ async function boot(argv) {
|
|
|
3392
3409
|
logger.debug(`provider auto-discovery skipped: ${toErrorMessage7(err)}`);
|
|
3393
3410
|
}
|
|
3394
3411
|
const isSingleShot = positional.length > 0 || typeof flags["prompt"] === "string";
|
|
3395
|
-
const isInteractiveTTY =
|
|
3412
|
+
const isInteractiveTTY = isStdinTTY4() && !isSingleShot && !flags["webui"] && !flags["no-interactive"] && !flags["skip"];
|
|
3396
3413
|
if (isInteractiveTTY) {
|
|
3397
3414
|
await checkGitInCwd({ cwd, renderer, reader });
|
|
3398
3415
|
const cont = await runProjectCheck({ projectRoot, cwd, renderer, reader });
|
|
@@ -3622,4 +3639,4 @@ async function initializeCli(argv, options = {}) {
|
|
|
3622
3639
|
export {
|
|
3623
3640
|
initializeCli
|
|
3624
3641
|
};
|
|
3625
|
-
//# sourceMappingURL=cli-context-
|
|
3642
|
+
//# sourceMappingURL=cli-context-CQYGIWOU.js.map
|