@wrongstack/cli 0.306.3 → 0.307.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/dist/{auth-L3WGSGDX.js → auth-TVOOHL4Q.js} +45 -106
- package/dist/boot/short-circuit-flags.d.ts +2 -2
- package/dist/chimera-cascade-evidence.d.ts +1 -1
- package/dist/chunk-2VMJ3E5Z.js +71 -0
- package/dist/{chunk-5N34EWJR.js → chunk-2ZNBRZ4W.js} +2 -2
- package/dist/{chunk-RHLQT3EV.js → chunk-CB35UVXO.js} +1636 -1528
- package/dist/{chunk-YKBRFSGL.js → chunk-DOJLAULS.js} +28 -28
- package/dist/{chunk-JUHRI6OV.js → chunk-G7337TTK.js} +24 -5
- package/dist/{chunk-KXN5HZDL.js → chunk-PKHGLWUJ.js} +24 -6
- package/dist/{chunk-HITHEXE3.js → chunk-TOG7OMKJ.js} +2 -2
- package/dist/{chunk-ARWGQUB3.js → chunk-XSG33WHN.js} +15 -5
- package/dist/{cli-main-3PUWFKSL.js → cli-main-YDOZZOZA.js} +29026 -28205
- package/dist/cli-main.d.ts +0 -20
- package/dist/{execution-4IG5XKOL.js → execution-CGT6J5ZN.js} +306 -274
- package/dist/fleet/host-learning-scheduler.d.ts +27 -0
- package/dist/fleet/host-shadow-manager.d.ts +64 -0
- package/dist/fleet/host.d.ts +5 -140
- package/dist/{hq-ZK6PGN3W.js → hq-PA6RH2UW.js} +2 -2
- package/dist/hq-server/mailbox-gateway-manager.d.ts +32 -0
- package/dist/hq-server/routes/auth/bootstrap-routes.d.ts +5 -0
- package/dist/hq-server/routes/auth/common.d.ts +11 -0
- package/dist/hq-server/routes/auth/password-routes.d.ts +9 -0
- package/dist/hq-server/routes/auth/session-audit-routes.d.ts +6 -0
- package/dist/hq-server/routes/auth/totp-routes.d.ts +9 -0
- package/dist/hq-server/routes/auth-handlers.d.ts +5 -132
- package/dist/hq-server/routes/command-handlers.d.ts +7 -0
- package/dist/hq-server/routes/data-handlers.d.ts +8 -0
- package/dist/hq-server/routes/mailbox-handlers.d.ts +22 -0
- package/dist/hq-server/routes.d.ts +3 -3
- package/dist/hq-server/server-lifecycle.d.ts +37 -0
- package/dist/hq-server/snapshot.d.ts +6 -5
- package/dist/hq-server/types.d.ts +4 -0
- package/dist/hq-server/upgrade-handler.d.ts +34 -0
- package/dist/hq-server/ws-client-events.d.ts +25 -0
- package/dist/hq-server/ws-leader.d.ts +47 -0
- package/dist/hq-server/ws-resume.d.ts +27 -0
- package/dist/hq-server/ws.d.ts +4 -71
- package/dist/{hq-server-IVZLVCFV.js → hq-server-PBRU275L.js} +2 -2
- package/dist/hq-server.d.ts +0 -38
- package/dist/index.js +1267 -122
- package/dist/{mcp-JNWEQ6T2.js → mcp-CMLFHRG2.js} +19 -9
- package/dist/mcp-serve.d.ts +31 -1
- package/dist/{modeldiag-6VS5KDP5.js → modeldiag-ICMPHT5L.js} +868 -831
- package/dist/{project-manifest-GE25PW4S.js → project-manifest-YFTJ3D5N.js} +2 -2
- package/dist/{project-picker-BOCWHBXP.js → project-picker-R5TYAE3Q.js} +3 -3
- package/dist/{providers-models-HQN3AT3K.js → providers-models-4FAKM2WO.js} +4 -4
- package/dist/repl-eternal-loop.d.ts +8 -0
- package/dist/repl-goal-banner.d.ts +21 -0
- package/dist/slash-commands/brain-council.d.ts +36 -0
- package/dist/slash-commands/brain-status.d.ts +12 -0
- package/dist/slash-commands/fallback.d.ts +6 -0
- package/dist/slash-commands/kanban-board-handlers.d.ts +13 -0
- package/dist/slash-commands/kanban-lifecycle-diagnostics.d.ts +16 -0
- package/dist/slash-commands/kanban-task-subcommands.d.ts +8 -0
- package/dist/slash-commands/memory-audience.d.ts +14 -0
- package/dist/slash-commands/memory-gather.d.ts +9 -0
- package/dist/slash-commands/memory-stats.d.ts +5 -0
- package/dist/slash-commands/settings-mutations.d.ts +6 -0
- package/dist/slash-commands/settings-view.d.ts +5 -0
- package/dist/subcommands/handlers/modeldiag-bench.d.ts +10 -0
- package/dist/subcommands/handlers/modeldiag-eval.d.ts +27 -0
- package/dist/subcommands/handlers/modeldiag-test.d.ts +8 -0
- package/dist/{version-help-ASKQYXDJ.js → version-help-TFD6VPF3.js} +2 -2
- package/dist/vibe-protocol-wiring.d.ts +10 -0
- package/dist/webui-server/credential-watcher.d.ts +15 -0
- package/dist/webui-server/domain-handlers.d.ts +21 -0
- package/dist/webui-server/route-contexts.d.ts +41 -0
- package/dist/{webui-server-FTG7JAZU.js → webui-server-IPHGJGXE.js} +515 -437
- package/dist/wiring/cli-execute-builder.d.ts +88 -0
- package/dist/wiring/cli-heap-watchdog.d.ts +33 -0
- package/dist/wiring/cli-prompt-and-tools-setup.d.ts +25 -0
- package/dist/wiring/cli-slash-commands-setup.d.ts +79 -0
- package/dist/wiring/heap-watchdog-setup.d.ts +53 -0
- package/dist/wiring/metrics.d.ts +1 -0
- package/dist/wiring/replay-governance-setup.d.ts +31 -0
- package/package.json +27 -27
package/dist/index.js
CHANGED
|
@@ -6,25 +6,18 @@ import {
|
|
|
6
6
|
makePromptDelegate,
|
|
7
7
|
renderAgentsTemplate,
|
|
8
8
|
renderDiff
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-DOJLAULS.js";
|
|
10
10
|
import {
|
|
11
11
|
theme
|
|
12
12
|
} from "./chunk-QD544J2B.js";
|
|
13
|
-
import {
|
|
14
|
-
fmtTok,
|
|
15
|
-
patchConfig
|
|
16
|
-
} from "./chunk-TYO2OVAD.js";
|
|
17
13
|
import {
|
|
18
14
|
parseWebuiSessionChildOptions,
|
|
19
15
|
writeWebuiSessionChildError
|
|
20
16
|
} from "./chunk-3JPTNADJ.js";
|
|
21
17
|
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import {
|
|
26
|
-
CLI_VERSION
|
|
27
|
-
} from "./chunk-XJXDOF63.js";
|
|
18
|
+
fmtTok,
|
|
19
|
+
patchConfig
|
|
20
|
+
} from "./chunk-TYO2OVAD.js";
|
|
28
21
|
import {
|
|
29
22
|
discoverAndMergeProviders
|
|
30
23
|
} from "./chunk-52C7PD2H.js";
|
|
@@ -35,28 +28,38 @@ import "./chunk-U3SS4NRH.js";
|
|
|
35
28
|
import "./chunk-NUIHRGPY.js";
|
|
36
29
|
import {
|
|
37
30
|
DEFAULT_PORT
|
|
38
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-CB35UVXO.js";
|
|
39
32
|
import "./chunk-KE7E7DPX.js";
|
|
40
33
|
import "./chunk-Q5GTM25S.js";
|
|
34
|
+
import {
|
|
35
|
+
helpCmd,
|
|
36
|
+
versionCmd
|
|
37
|
+
} from "./chunk-XSG33WHN.js";
|
|
38
|
+
import {
|
|
39
|
+
CLI_VERSION
|
|
40
|
+
} from "./chunk-XJXDOF63.js";
|
|
41
|
+
import {
|
|
42
|
+
renderAuthLocalHelpToString
|
|
43
|
+
} from "./chunk-2VMJ3E5Z.js";
|
|
41
44
|
import {
|
|
42
45
|
parseArgs,
|
|
43
46
|
runPicker,
|
|
44
47
|
saveToGlobalConfig
|
|
45
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-PKHGLWUJ.js";
|
|
49
|
+
import "./chunk-B4JLSXZB.js";
|
|
46
50
|
import {
|
|
47
51
|
isKeylessLocalProvider,
|
|
48
52
|
visibleModelIds
|
|
49
53
|
} from "./chunk-VUVOMXWP.js";
|
|
54
|
+
import {
|
|
55
|
+
activeProfileConfigPath
|
|
56
|
+
} from "./chunk-YMXXOOFN.js";
|
|
50
57
|
import {
|
|
51
58
|
mutateConfigProviders,
|
|
52
59
|
normalizeKeys,
|
|
53
60
|
resolveActiveApiKey,
|
|
54
61
|
writeKeysBack
|
|
55
62
|
} from "./chunk-SZ42FYPT.js";
|
|
56
|
-
import "./chunk-B4JLSXZB.js";
|
|
57
|
-
import {
|
|
58
|
-
activeProfileConfigPath
|
|
59
|
-
} from "./chunk-YMXXOOFN.js";
|
|
60
63
|
import "./chunk-7OCVIDC7.js";
|
|
61
64
|
|
|
62
65
|
// src/cli-context.ts
|
|
@@ -714,11 +717,1126 @@ async function launchDesktop(args) {
|
|
|
714
717
|
});
|
|
715
718
|
}
|
|
716
719
|
|
|
720
|
+
// src/subcommands/handlers/per-subcommand-help.ts
|
|
721
|
+
import { color as color5 } from "@wrongstack/core/utils";
|
|
722
|
+
|
|
723
|
+
// src/subcommands/handlers/bench-run-help.ts
|
|
724
|
+
import { color as color3 } from "@wrongstack/core/utils";
|
|
725
|
+
var BENCH_RUN_FLAGS = [
|
|
726
|
+
// -- Suite selection ------------------------------------------------
|
|
727
|
+
{
|
|
728
|
+
name: "suite",
|
|
729
|
+
flag: "--suite <id>",
|
|
730
|
+
description: "Benchmark suite id (`polyglot` or `swebench`).",
|
|
731
|
+
group: "suite",
|
|
732
|
+
kind: "value",
|
|
733
|
+
defaultValue: "polyglot"
|
|
734
|
+
},
|
|
735
|
+
{
|
|
736
|
+
name: "polyglot-dir",
|
|
737
|
+
flag: "--polyglot-dir <path>",
|
|
738
|
+
description: "Path to the Aider polyglot dataset (required when --suite polyglot).",
|
|
739
|
+
group: "suite",
|
|
740
|
+
kind: "value",
|
|
741
|
+
required: true
|
|
742
|
+
},
|
|
743
|
+
{
|
|
744
|
+
name: "languages",
|
|
745
|
+
flag: "--languages <csv>",
|
|
746
|
+
description: "Comma-separated language list to filter the polyglot suite (e.g. `python,go`).",
|
|
747
|
+
group: "suite",
|
|
748
|
+
kind: "value"
|
|
749
|
+
},
|
|
750
|
+
{
|
|
751
|
+
name: "dataset-dir",
|
|
752
|
+
flag: "--dataset-dir <path>",
|
|
753
|
+
description: "Path to the SWE-bench Verified dataset (optional, defaults to the official cache).",
|
|
754
|
+
group: "suite",
|
|
755
|
+
kind: "value"
|
|
756
|
+
},
|
|
757
|
+
{
|
|
758
|
+
name: "docker",
|
|
759
|
+
flag: "--docker",
|
|
760
|
+
description: "Enable the SWE-bench Docker runtime (required for live grading).",
|
|
761
|
+
group: "suite",
|
|
762
|
+
kind: "boolean"
|
|
763
|
+
},
|
|
764
|
+
// -- Model matrix ---------------------------------------------------
|
|
765
|
+
{
|
|
766
|
+
name: "models",
|
|
767
|
+
flag: "--models <config>",
|
|
768
|
+
description: "Path to the model-cells config (JSON).",
|
|
769
|
+
group: "models",
|
|
770
|
+
kind: "value",
|
|
771
|
+
defaultValue: "bench.config.json"
|
|
772
|
+
},
|
|
773
|
+
// -- Run control ----------------------------------------------------
|
|
774
|
+
{
|
|
775
|
+
name: "limit",
|
|
776
|
+
flag: "--limit <N>",
|
|
777
|
+
description: "Cap the number of tasks per cell (useful for smoke tests).",
|
|
778
|
+
group: "control",
|
|
779
|
+
kind: "value"
|
|
780
|
+
},
|
|
781
|
+
{
|
|
782
|
+
name: "out",
|
|
783
|
+
flag: "--out <dir>",
|
|
784
|
+
description: "Base directory for run output (each run gets a timestamped subdir).",
|
|
785
|
+
group: "control",
|
|
786
|
+
kind: "value",
|
|
787
|
+
defaultValue: "bench-results"
|
|
788
|
+
},
|
|
789
|
+
{
|
|
790
|
+
name: "concurrency",
|
|
791
|
+
flag: "--concurrency <N>",
|
|
792
|
+
description: "Override the per-cell concurrency from the model config.",
|
|
793
|
+
group: "control",
|
|
794
|
+
kind: "value"
|
|
795
|
+
}
|
|
796
|
+
];
|
|
797
|
+
var BENCH_RUN_BOOLEAN_FLAG_NAMES = BENCH_RUN_FLAGS.filter(
|
|
798
|
+
(f) => f.kind === "boolean"
|
|
799
|
+
).map((f) => f.name);
|
|
800
|
+
var BENCH_RUN_VALUE_FLAG_NAMES = BENCH_RUN_FLAGS.filter(
|
|
801
|
+
(f) => f.kind === "value"
|
|
802
|
+
).map((f) => f.name);
|
|
803
|
+
var BENCH_RUN_FLAG_COLUMN_WIDTH = 28;
|
|
804
|
+
function renderBenchRunHelpToString() {
|
|
805
|
+
const lines = [
|
|
806
|
+
color3.bold("wstack bench run \u2014 execute a benchmark suite across a model matrix"),
|
|
807
|
+
color3.dim(" Runs a benchmark suite (polyglot or swebench) across every model cell"),
|
|
808
|
+
color3.dim(" in the config. Output is a per-run directory with `report.md`, JSON"),
|
|
809
|
+
color3.dim(" artifacts, and (for swebench) per-cell predictions for the official"),
|
|
810
|
+
color3.dim(" harness."),
|
|
811
|
+
"",
|
|
812
|
+
color3.bold("Usage"),
|
|
813
|
+
` ${buildUsageLine()}`,
|
|
814
|
+
"",
|
|
815
|
+
color3.bold("Flags"),
|
|
816
|
+
...buildFlagBlock(),
|
|
817
|
+
"",
|
|
818
|
+
color3.dim(
|
|
819
|
+
"See also: wstack bench list (show available suites + cells); wstack bench report <dir>"
|
|
820
|
+
)
|
|
821
|
+
];
|
|
822
|
+
return lines.join("\n") + "\n";
|
|
823
|
+
}
|
|
824
|
+
function buildUsageLine() {
|
|
825
|
+
const parts = ["wstack bench run"];
|
|
826
|
+
for (const f of BENCH_RUN_FLAGS) {
|
|
827
|
+
if (f.kind === "value") {
|
|
828
|
+
parts.push(`[${f.flag}]`);
|
|
829
|
+
} else {
|
|
830
|
+
parts.push(`[${f.flag}]`);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
return parts.join(" ");
|
|
834
|
+
}
|
|
835
|
+
function buildFlagBlock() {
|
|
836
|
+
const rows = [];
|
|
837
|
+
let currentGroup;
|
|
838
|
+
for (const f of BENCH_RUN_FLAGS) {
|
|
839
|
+
if (f.group !== currentGroup) {
|
|
840
|
+
const header = f.group === "suite" ? "Suite selection:" : f.group === "models" ? "Model matrix:" : "Run control:";
|
|
841
|
+
rows.push(color3.dim(` ${header}`));
|
|
842
|
+
currentGroup = f.group;
|
|
843
|
+
}
|
|
844
|
+
const paddedFlag = f.flag.padEnd(BENCH_RUN_FLAG_COLUMN_WIDTH, " ");
|
|
845
|
+
let desc = f.description;
|
|
846
|
+
if (f.required) {
|
|
847
|
+
desc = desc + " " + color3.bold("(required)");
|
|
848
|
+
} else if (f.defaultValue !== void 0) {
|
|
849
|
+
desc = desc + " " + color3.dim(`(default: ${f.defaultValue})`);
|
|
850
|
+
}
|
|
851
|
+
rows.push(` ${paddedFlag} ${desc}`);
|
|
852
|
+
}
|
|
853
|
+
return rows;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
// src/subcommands/handlers/models-add-help.ts
|
|
857
|
+
import { color as color4 } from "@wrongstack/core/utils";
|
|
858
|
+
var MODELS_ADD_FLAGS = [
|
|
859
|
+
// -- Identity --------------------------------------------------------
|
|
860
|
+
{
|
|
861
|
+
name: "provider",
|
|
862
|
+
flag: "--provider <id>",
|
|
863
|
+
description: "Provider id the model belongs to (defaults to the saved alias).",
|
|
864
|
+
group: "identity",
|
|
865
|
+
kind: "value"
|
|
866
|
+
},
|
|
867
|
+
{
|
|
868
|
+
name: "name",
|
|
869
|
+
flag: "--name <name>",
|
|
870
|
+
description: "Human-readable display name (defaults to <mid>).",
|
|
871
|
+
group: "identity",
|
|
872
|
+
kind: "value"
|
|
873
|
+
},
|
|
874
|
+
// -- Capabilities ---------------------------------------------------
|
|
875
|
+
{
|
|
876
|
+
name: "max-context",
|
|
877
|
+
flag: "--max-context <N>",
|
|
878
|
+
description: "Context window in tokens (e.g. 200000 for 200k, or `128k`).",
|
|
879
|
+
group: "capabilities",
|
|
880
|
+
kind: "value"
|
|
881
|
+
},
|
|
882
|
+
{
|
|
883
|
+
name: "max-output",
|
|
884
|
+
flag: "--max-output <N>",
|
|
885
|
+
description: "Max output tokens per request.",
|
|
886
|
+
group: "capabilities",
|
|
887
|
+
kind: "value"
|
|
888
|
+
},
|
|
889
|
+
{
|
|
890
|
+
name: "tools",
|
|
891
|
+
flag: "--tools / --no-tools",
|
|
892
|
+
description: "Toggle tool/function-calling support.",
|
|
893
|
+
group: "capabilities",
|
|
894
|
+
kind: "boolean"
|
|
895
|
+
},
|
|
896
|
+
{
|
|
897
|
+
name: "vision",
|
|
898
|
+
flag: "--vision / --no-vision",
|
|
899
|
+
description: "Toggle image-input support.",
|
|
900
|
+
group: "capabilities",
|
|
901
|
+
kind: "boolean"
|
|
902
|
+
},
|
|
903
|
+
{
|
|
904
|
+
name: "reasoning",
|
|
905
|
+
flag: "--reasoning / --no-reasoning",
|
|
906
|
+
description: "Mark the model as a reasoning model.",
|
|
907
|
+
group: "capabilities",
|
|
908
|
+
kind: "boolean"
|
|
909
|
+
},
|
|
910
|
+
{
|
|
911
|
+
name: "streaming",
|
|
912
|
+
flag: "--streaming / --no-streaming",
|
|
913
|
+
description: "Toggle streaming response support.",
|
|
914
|
+
group: "capabilities",
|
|
915
|
+
kind: "boolean"
|
|
916
|
+
},
|
|
917
|
+
{
|
|
918
|
+
name: "json-mode",
|
|
919
|
+
flag: "--json-mode",
|
|
920
|
+
description: "Mark the model as supporting native JSON output.",
|
|
921
|
+
group: "capabilities",
|
|
922
|
+
kind: "boolean"
|
|
923
|
+
}
|
|
924
|
+
];
|
|
925
|
+
var MODELS_ADD_BOOLEAN_FLAG_NAMES = MODELS_ADD_FLAGS.filter(
|
|
926
|
+
(f) => f.kind === "boolean"
|
|
927
|
+
).map((f) => f.name);
|
|
928
|
+
var MODELS_ADD_VALUE_FLAG_NAMES = MODELS_ADD_FLAGS.filter(
|
|
929
|
+
(f) => f.kind === "value"
|
|
930
|
+
).map((f) => f.name);
|
|
931
|
+
var MODELS_ADD_FLAG_COLUMN_WIDTH = 30;
|
|
932
|
+
function renderModelsAddHelpToString() {
|
|
933
|
+
const lines = [
|
|
934
|
+
color4.bold("wstack models add <mid> \u2014 register a custom model"),
|
|
935
|
+
color4.dim(" Add or override a custom model (for self-hosted endpoints, fine-tuned"),
|
|
936
|
+
color4.dim(" weights, or models not in the public models.dev catalog). The flags are"),
|
|
937
|
+
color4.dim(" organized into two groups: identity (`--provider`, `--name`) and"),
|
|
938
|
+
color4.dim(" capabilities (`--max-context`, `--tools`, `--vision`, etc.)."),
|
|
939
|
+
"",
|
|
940
|
+
color4.bold("Usage"),
|
|
941
|
+
` ${buildUsageLine2()}`,
|
|
942
|
+
"",
|
|
943
|
+
color4.bold("Flags"),
|
|
944
|
+
...buildFlagBlock2(),
|
|
945
|
+
"",
|
|
946
|
+
color4.dim("See also: wstack models list (verify the entry); wstack models remove")
|
|
947
|
+
];
|
|
948
|
+
return lines.join("\n") + "\n";
|
|
949
|
+
}
|
|
950
|
+
function buildUsageLine2() {
|
|
951
|
+
const parts = ["wstack models add <mid>"];
|
|
952
|
+
for (const f of MODELS_ADD_FLAGS) {
|
|
953
|
+
if (f.kind === "value") {
|
|
954
|
+
parts.push(`[${f.flag}]`);
|
|
955
|
+
} else {
|
|
956
|
+
parts.push(`[${f.flag}]`);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
return parts.join(" ");
|
|
960
|
+
}
|
|
961
|
+
function buildFlagBlock2() {
|
|
962
|
+
const rows = [];
|
|
963
|
+
let currentGroup;
|
|
964
|
+
for (const f of MODELS_ADD_FLAGS) {
|
|
965
|
+
if (f.group !== currentGroup) {
|
|
966
|
+
const header = f.group === "identity" ? "Identity:" : "Capabilities:";
|
|
967
|
+
rows.push(color4.dim(` ${header}`));
|
|
968
|
+
currentGroup = f.group;
|
|
969
|
+
}
|
|
970
|
+
const paddedFlag = f.flag.padEnd(MODELS_ADD_FLAG_COLUMN_WIDTH, " ");
|
|
971
|
+
rows.push(` ${paddedFlag} ${f.description}`);
|
|
972
|
+
}
|
|
973
|
+
return rows;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// src/subcommands/handlers/per-subcommand-deep-help-table.ts
|
|
977
|
+
var deepHelpTable = {
|
|
978
|
+
// -- mcp -----------------------------------------------------------------
|
|
979
|
+
"mcp:add": {
|
|
980
|
+
name: "mcp:add",
|
|
981
|
+
title: "wstack mcp add <name> \u2014 register a built-in MCP server",
|
|
982
|
+
description: "Register a built-in MCP server by alias (e.g. `github`, `playwright`) and write the entry to the global config. The server is added in `disabled` state by default; pass `--enable` to register it active immediately.",
|
|
983
|
+
usage: "wstack mcp add <name> [--enable]",
|
|
984
|
+
subcommands: [
|
|
985
|
+
{
|
|
986
|
+
name: "<name>",
|
|
987
|
+
description: "The built-in server alias (run `wstack mcp add` for the list)."
|
|
988
|
+
},
|
|
989
|
+
{
|
|
990
|
+
name: "--enable / -e",
|
|
991
|
+
description: "Register the server enabled (default: disabled until you opt in)."
|
|
992
|
+
}
|
|
993
|
+
],
|
|
994
|
+
seeAlso: "wstack mcp list (verify the entry landed); wstack mcp remove"
|
|
995
|
+
},
|
|
996
|
+
"mcp:remove": {
|
|
997
|
+
name: "mcp:remove",
|
|
998
|
+
title: "wstack mcp remove <name> \u2014 unregister an MCP server",
|
|
999
|
+
description: "Unregister an MCP server by alias. Removes the entry from the global config; the server process is not killed (REPL restart required to fully tear down the running process).",
|
|
1000
|
+
usage: "wstack mcp remove <name>",
|
|
1001
|
+
subcommands: [{ name: "<name>", description: "The server alias to unregister." }]
|
|
1002
|
+
},
|
|
1003
|
+
// -- plugin --------------------------------------------------------------
|
|
1004
|
+
"plugin:add": {
|
|
1005
|
+
name: "plugin:add",
|
|
1006
|
+
title: "wstack plugin add <spec> \u2014 install a tool plugin",
|
|
1007
|
+
description: "Add a tool plugin by specifier (npm package name) or official alias (`telegram`, `lsp`). Pass `--disabled` to install the plugin but leave it off until you explicitly enable it. The plugin requires a restart of the wrongstack process to take effect.",
|
|
1008
|
+
usage: "wstack plugin add <spec|alias> [--disabled]",
|
|
1009
|
+
subcommands: [
|
|
1010
|
+
{
|
|
1011
|
+
name: "<spec|alias>",
|
|
1012
|
+
description: "NPM specifier (e.g. `@org/wrongstack-x`) or official alias."
|
|
1013
|
+
},
|
|
1014
|
+
{
|
|
1015
|
+
name: "--disabled",
|
|
1016
|
+
description: "Install the plugin but leave it disabled until you enable it."
|
|
1017
|
+
}
|
|
1018
|
+
],
|
|
1019
|
+
seeAlso: "wstack plugin official (list the official registry); wstack plugin enable"
|
|
1020
|
+
},
|
|
1021
|
+
"plugin:remove": {
|
|
1022
|
+
name: "plugin:remove",
|
|
1023
|
+
title: "wstack plugin remove <spec> \u2014 uninstall a tool plugin",
|
|
1024
|
+
description: "Remove a tool plugin from the config. The plugin requires a restart of the wrongstack process to take effect. Aliases: `rm`, `uninstall`.",
|
|
1025
|
+
usage: "wstack plugin remove <spec|alias>",
|
|
1026
|
+
subcommands: [
|
|
1027
|
+
{ name: "<spec|alias>", description: "The specifier or official alias to remove." }
|
|
1028
|
+
]
|
|
1029
|
+
},
|
|
1030
|
+
"plugin:enable": {
|
|
1031
|
+
name: "plugin:enable",
|
|
1032
|
+
title: "wstack plugin enable <spec> \u2014 re-enable a previously-disabled plugin",
|
|
1033
|
+
description: "Re-enable a plugin that was installed with `--disabled` or toggled off with `wstack plugin disable`. Requires a restart.",
|
|
1034
|
+
usage: "wstack plugin enable <spec|alias>",
|
|
1035
|
+
subcommands: [
|
|
1036
|
+
{ name: "<spec|alias>", description: "The specifier or official alias to enable." }
|
|
1037
|
+
]
|
|
1038
|
+
},
|
|
1039
|
+
"plugin:disable": {
|
|
1040
|
+
name: "plugin:disable",
|
|
1041
|
+
title: "wstack plugin disable <spec> \u2014 temporarily disable a plugin",
|
|
1042
|
+
description: "Temporarily disable a plugin without removing it from the config. Use `wstack plugin enable` to re-enable. Requires a restart.",
|
|
1043
|
+
usage: "wstack plugin disable <spec|alias>",
|
|
1044
|
+
subcommands: [
|
|
1045
|
+
{ name: "<spec|alias>", description: "The specifier or official alias to disable." }
|
|
1046
|
+
]
|
|
1047
|
+
},
|
|
1048
|
+
"plugin:toggle": {
|
|
1049
|
+
name: "plugin:toggle",
|
|
1050
|
+
title: "wstack plugin toggle <name> \u2014 toggle an audit-list plugin row",
|
|
1051
|
+
description: "Toggle one built-in audit-list plugin by its runtime name. Default-active plugins are disabled by writing `{ enabled: false }` overrides; enabling them again removes that override. All bundled audit-list rows are toggleable; future non-toggleable rows are reported as locked. Requires a restart for loaded plugin code to change in the current session.",
|
|
1052
|
+
usage: "wstack plugin toggle <name>",
|
|
1053
|
+
subcommands: [
|
|
1054
|
+
{ name: "<name>", description: "Audit-list runtime name, e.g. `format-on-save`." }
|
|
1055
|
+
],
|
|
1056
|
+
seeAlso: "wstack plugin report (see effective state and toggle policy)"
|
|
1057
|
+
},
|
|
1058
|
+
"plugin:report": {
|
|
1059
|
+
name: "plugin:report",
|
|
1060
|
+
title: "wstack plugin report \u2014 show the plugin audit table",
|
|
1061
|
+
description: "Print the built-in plugin audit table. Each row shows effective state, whether that state came from config or default boot behavior, risk, and the toggle policy for that row.",
|
|
1062
|
+
usage: "wstack plugin report (alias: wstack plugin audit)",
|
|
1063
|
+
seeAlso: "wstack plugin toggle <name> (toggle audit-list rows); wstack plugin list"
|
|
1064
|
+
},
|
|
1065
|
+
"plugin:menu": {
|
|
1066
|
+
name: "plugin:menu",
|
|
1067
|
+
title: "wstack plugin menu \u2014 open or describe the plugin picker",
|
|
1068
|
+
description: "In the TUI, `/plugin menu` opens the interactive plugin picker. From the non-interactive `wstack plugin menu` surface, the command prints the same audit report as `wstack plugin report`.",
|
|
1069
|
+
usage: "wstack plugin menu",
|
|
1070
|
+
seeAlso: "/plugin menu (interactive picker in the TUI); wstack plugin report"
|
|
1071
|
+
},
|
|
1072
|
+
// -- models --------------------------------------------------------------
|
|
1073
|
+
// The `models:add` deep entry delegates its body to
|
|
1074
|
+
// `models-add-help.ts` via the `customBody` field. The flag
|
|
1075
|
+
// list lives in exactly one place (`MODELS_ADD_FLAGS`), and
|
|
1076
|
+
// every surface that renders the help — `wstack models add --help`,
|
|
1077
|
+
// `/models add help`, `/help models add` — produces the same
|
|
1078
|
+
// string. The `title` / `description` / `usage` / `seeAlso`
|
|
1079
|
+
// fields below are required by the `PerSubcommandHelp` shape
|
|
1080
|
+
// but never rendered (the `customBody` thunk owns the full
|
|
1081
|
+
// layout). They're filled in with sensible defaults so a
|
|
1082
|
+
// future refactor that drops `customBody` (e.g. to use the
|
|
1083
|
+
// standard layout) still has a coherent fallback.
|
|
1084
|
+
"models:add": {
|
|
1085
|
+
name: "models:add",
|
|
1086
|
+
title: "wstack models add <mid> \u2014 register a custom model",
|
|
1087
|
+
description: "See renderModelsAddHelpToString() in models-add-help.ts for the full block.",
|
|
1088
|
+
usage: "wstack models add <mid> [...flags]",
|
|
1089
|
+
customBody: renderModelsAddHelpToString
|
|
1090
|
+
},
|
|
1091
|
+
"models:remove": {
|
|
1092
|
+
name: "models:remove",
|
|
1093
|
+
title: "wstack models remove <mid> \u2014 unregister a custom model",
|
|
1094
|
+
description: "Remove a custom model from the config. The catalog is unaffected (catalog models are managed by `wstack models refresh`).",
|
|
1095
|
+
usage: "wstack models remove <mid>",
|
|
1096
|
+
subcommands: [{ name: "<mid>", description: "The model id to remove." }]
|
|
1097
|
+
},
|
|
1098
|
+
// -- audit / replay (--list deep-subcommand) ---------------------------
|
|
1099
|
+
"audit:list": {
|
|
1100
|
+
name: "audit:list",
|
|
1101
|
+
title: "wstack audit --list \u2014 list every session with an audit log",
|
|
1102
|
+
description: "Scan the project sessions dir for `.audit.jsonl` sidecars and print a one-line summary per session (entry count + chain status). Useful for finding a session to inspect with `wstack audit <id>`.",
|
|
1103
|
+
usage: "wstack audit --list / wstack audit -l",
|
|
1104
|
+
seeAlso: "wstack audit <id> (inspect a single session's chain)"
|
|
1105
|
+
},
|
|
1106
|
+
"replay:list": {
|
|
1107
|
+
name: "replay:list",
|
|
1108
|
+
title: "wstack replay --list \u2014 list every session with a replay log",
|
|
1109
|
+
description: "Scan the project sessions dir for `.replay.jsonl` sidecars and print a one-line summary per session (entry count + log path). Useful for finding a session to inspect with `wstack replay <id>`.",
|
|
1110
|
+
usage: "wstack replay --list / wstack replay -l",
|
|
1111
|
+
seeAlso: "wstack replay <id> (inspect a single session's recorded responses)"
|
|
1112
|
+
},
|
|
1113
|
+
// -- sessions (deep subcommands) ---------------------------------------
|
|
1114
|
+
"sessions:resume": {
|
|
1115
|
+
name: "sessions:resume",
|
|
1116
|
+
title: "wstack sessions resume [<id>] \u2014 resume a prior session",
|
|
1117
|
+
description: `Resume a session by id, or the most recent one if no id is given. The REPL replays the session's history into the new run so context is preserved. Use the most recent id when the user just asked "pick up where we left off" without naming a specific session.`,
|
|
1118
|
+
usage: "wstack sessions resume [<id>]",
|
|
1119
|
+
subcommands: [
|
|
1120
|
+
{ name: "[<id>]", description: "Session id to resume (defaults to the most recent)." }
|
|
1121
|
+
],
|
|
1122
|
+
seeAlso: "wstack sessions list (find a recent id); wstack sessions show <id> (preview before resuming)"
|
|
1123
|
+
},
|
|
1124
|
+
"sessions:fork": {
|
|
1125
|
+
name: "sessions:fork",
|
|
1126
|
+
title: "wstack sessions fork [<id>] [--to N] \u2014 branch a session journal",
|
|
1127
|
+
description: "Create a non-destructive child JSONL journal from the latest persisted boundary or checkpoint N. The parent is unchanged and the returned checkpoint hash identifies the exact parent event prefix. New Git-backed checkpoints also report a content-addressed workspace manifest, but the fork command does not apply it automatically: files remain shared until a host materializes that manifest into a separate clean checkout.",
|
|
1128
|
+
usage: "wstack sessions fork [<id>] [--to N]",
|
|
1129
|
+
subcommands: [
|
|
1130
|
+
{ name: "[<id>]", description: "Parent session id (defaults to the most recent)." },
|
|
1131
|
+
{ name: "--to N", description: "Fork at checkpoint prompt index N." }
|
|
1132
|
+
],
|
|
1133
|
+
seeAlso: "wstack rewind --list (find checkpoints); wstack sessions resume <child-id>"
|
|
1134
|
+
},
|
|
1135
|
+
"sessions:fleet": {
|
|
1136
|
+
name: "sessions:fleet",
|
|
1137
|
+
title: "wstack sessions fleet \u2014 list the active fleet of sessions",
|
|
1138
|
+
description: "List the active multi-agent fleet runs (the director, the subagent set, the iteration count, the journal size). Distinct from `wstack sessions list` which only shows single-agent sessions.",
|
|
1139
|
+
usage: "wstack sessions fleet",
|
|
1140
|
+
seeAlso: "wstack sessions list (single-agent sessions); /fleet (the in-REPL equivalent)"
|
|
1141
|
+
},
|
|
1142
|
+
"sessions:show": {
|
|
1143
|
+
name: "sessions:show",
|
|
1144
|
+
title: "wstack sessions show <id> \u2014 preview a session in detail",
|
|
1145
|
+
description: "Print the session metadata, the first N turns, the token/cost totals, and any errors. Use this to decide whether to resume a session before committing to it.",
|
|
1146
|
+
usage: "wstack sessions show <id>",
|
|
1147
|
+
subcommands: [{ name: "<id>", description: "The session id to show." }]
|
|
1148
|
+
},
|
|
1149
|
+
"sessions:list": {
|
|
1150
|
+
name: "sessions:list",
|
|
1151
|
+
title: "wstack sessions list \u2014 list recent single-agent sessions",
|
|
1152
|
+
description: "Print a one-line summary per recorded session (id, timestamp, last prompt, model, token totals). Distinct from `wstack sessions fleet` which shows active multi-agent runs. Use this to find a session id to resume, show, or export.",
|
|
1153
|
+
usage: "wstack sessions list",
|
|
1154
|
+
seeAlso: "wstack sessions fleet (active runs); wstack sessions resume <id> (resume one)"
|
|
1155
|
+
},
|
|
1156
|
+
"sessions:config": {
|
|
1157
|
+
name: "sessions:config",
|
|
1158
|
+
title: "wstack sessions config \u2014 session-specific config",
|
|
1159
|
+
description: "Show or edit the session-specific config overrides (e.g. per-session provider + model). Subcommand: see the underlying config-history commands for the full surface \u2014 this is the shortcut alias.",
|
|
1160
|
+
usage: "wstack sessions config"
|
|
1161
|
+
},
|
|
1162
|
+
// -- config (subcommands of the top-level config) ---------------------
|
|
1163
|
+
"config:show": {
|
|
1164
|
+
name: "config:show",
|
|
1165
|
+
title: "wstack config show \u2014 print the resolved config",
|
|
1166
|
+
description: "Print the resolved config (active profile plus all on-disk overrides applied) to stdout. Secrets are masked. The default subcommand \u2014 `wstack config` without a sub invokes this.",
|
|
1167
|
+
usage: "wstack config show",
|
|
1168
|
+
seeAlso: "wstack config edit (interactive); wstack auth (most config edits are auth/key changes)"
|
|
1169
|
+
},
|
|
1170
|
+
"config:edit": {
|
|
1171
|
+
name: "config:edit",
|
|
1172
|
+
title: "wstack config edit \u2014 open the active profile config in $EDITOR",
|
|
1173
|
+
description: "Print the active profile config path (typically `~/.wrongstack/profiles/default/config.json`) and the command to open it. Does not spawn the editor itself \u2014 the user runs the printed command (or sets `$EDITOR` and re-runs). Useful for offline edits when you want to see the full file at once.",
|
|
1174
|
+
usage: "wstack config edit",
|
|
1175
|
+
seeAlso: "wstack config show (verify after edit); wstack config history (audit trail)"
|
|
1176
|
+
},
|
|
1177
|
+
"config:history": {
|
|
1178
|
+
name: "config:history",
|
|
1179
|
+
title: "wstack config history \u2014 list recent config-history entries",
|
|
1180
|
+
description: "List every recent change to the active profile config, with a one-line description and a snapshot id. Pass `--id <id>` to see the full diff + masked snapshot. The audit trail is append-only (entries are never modified post-creation).",
|
|
1181
|
+
usage: "wstack config history [--id <id>]",
|
|
1182
|
+
subcommands: [
|
|
1183
|
+
{ name: "<no subcommand>", description: "List every history entry (newest first)." },
|
|
1184
|
+
{ name: "--id <id>", description: "Show the full diff + masked snapshot for one entry." }
|
|
1185
|
+
],
|
|
1186
|
+
seeAlso: "wstack config restore <id>|--latest (revert); wstack config show (current state)"
|
|
1187
|
+
},
|
|
1188
|
+
"config:restore": {
|
|
1189
|
+
name: "config:restore",
|
|
1190
|
+
title: "wstack config restore <id>|--latest \u2014 revert to a prior config",
|
|
1191
|
+
description: "Restore a previous config-history entry. Pass either the history id (from `wstack config history`) or `--latest` to revert to the most recent prior version. A backup of the current config is created before the restore, so the change is itself recorded in the history (a history of histories).",
|
|
1192
|
+
usage: "wstack config restore <id> | --latest / -l",
|
|
1193
|
+
subcommands: [
|
|
1194
|
+
{
|
|
1195
|
+
name: "<id>",
|
|
1196
|
+
description: "The history id to restore (from `wstack config history` output)."
|
|
1197
|
+
},
|
|
1198
|
+
{
|
|
1199
|
+
name: "--latest / -l",
|
|
1200
|
+
description: "Restore to the most recent prior version (without naming an id)."
|
|
1201
|
+
}
|
|
1202
|
+
],
|
|
1203
|
+
seeAlso: "wstack config history (list entries); wstack config show (verify the restore)"
|
|
1204
|
+
},
|
|
1205
|
+
// -- rewind (flag-shaped deep subcommands) ----------------------------
|
|
1206
|
+
"rewind:list": {
|
|
1207
|
+
name: "rewind:list",
|
|
1208
|
+
title: "wstack rewind --list \u2014 list rewind checkpoints for a session",
|
|
1209
|
+
description: "Print every checkpoint for the session (default: latest). Each checkpoint is a snapshot of the working tree + session history at a given prompt index. Use the checkpoint index as the value for `--to <idx>` when rewinding. Default `wstack rewind` (no flags) is an error \u2014 pair `--list` with a session id (positional) to discover available checkpoints first.",
|
|
1210
|
+
usage: "wstack rewind [<sessionId>] --list",
|
|
1211
|
+
seeAlso: "wstack rewind --to <idx> (rewind to a specific checkpoint); wstack rewind --all"
|
|
1212
|
+
},
|
|
1213
|
+
"rewind:all": {
|
|
1214
|
+
name: "rewind:all",
|
|
1215
|
+
title: "wstack rewind --all \u2014 rewind to the start of the session",
|
|
1216
|
+
description: "Rewind the working tree + session state to the very start of the session (the first prompt). Every file modified since the start is reverted. Pair with `--resume` to also truncate the session history at the start (so a fresh `wstack` invocation begins from there).",
|
|
1217
|
+
usage: "wstack rewind [<sessionId>] --all [--resume]",
|
|
1218
|
+
seeAlso: "wstack rewind --last N (rewind fewer steps); wstack rewind --to <idx> (specific checkpoint)"
|
|
1219
|
+
},
|
|
1220
|
+
"rewind:last": {
|
|
1221
|
+
name: "rewind:last",
|
|
1222
|
+
title: "wstack rewind --last N \u2014 rewind the last N prompts",
|
|
1223
|
+
description: "Rewind the last `N` prompts. For a session that was on track for prompts 1..10 and went off the rails at 11..15, `--last 5` rewinds to the state at the end of prompt 10. Pair with `--resume` to truncate the history at the rewound point.",
|
|
1224
|
+
usage: "wstack rewind [<sessionId>] --last <N> [--resume]",
|
|
1225
|
+
subcommands: [
|
|
1226
|
+
{ name: "<N>", description: "Number of recent prompts to rewind (must be \u2265 1)." }
|
|
1227
|
+
],
|
|
1228
|
+
seeAlso: "wstack rewind --all (rewind further); wstack rewind --to <idx> (precise checkpoint)"
|
|
1229
|
+
},
|
|
1230
|
+
"rewind:to": {
|
|
1231
|
+
name: "rewind:to",
|
|
1232
|
+
title: "wstack rewind --to <idx> \u2014 rewind to a specific checkpoint",
|
|
1233
|
+
description: "Rewind to checkpoint at the given prompt index (from `wstack rewind --list`). The most precise rewind form \u2014 lets you step back to exactly the state at a specific prompt rather than the bulk `--all` or approximate `--last N`.",
|
|
1234
|
+
usage: "wstack rewind [<sessionId>] --to <idx> [--resume]",
|
|
1235
|
+
subcommands: [
|
|
1236
|
+
{
|
|
1237
|
+
name: "<idx>",
|
|
1238
|
+
description: "Prompt index to rewind to (must be \u2265 0). Use `wstack rewind --list` to find indices."
|
|
1239
|
+
}
|
|
1240
|
+
],
|
|
1241
|
+
seeAlso: "wstack rewind --list (find checkpoint indices); wstack rewind --resume (truncate history at the checkpoint)"
|
|
1242
|
+
},
|
|
1243
|
+
"rewind:resume": {
|
|
1244
|
+
name: "rewind:resume",
|
|
1245
|
+
title: "wstack rewind --resume \u2014 truncate session history at the checkpoint",
|
|
1246
|
+
description: "After the rewind (any of `--all` / `--last N` / `--to N`), also truncate the session's recorded history at the rewound checkpoint so the next `wstack` invocation begins fresh from there. Without `--resume`, the rewind only reverts the working tree \u2014 the session history is preserved (you'd see the rewind point as a checkpoint in subsequent runs).",
|
|
1247
|
+
usage: "wstack rewind [<sessionId>] {--all|--last <N>|--to <idx>} --resume",
|
|
1248
|
+
seeAlso: "wstack rewind --list (find checkpoints); wstack sessions resume <id> (resume a rewound session)"
|
|
1249
|
+
},
|
|
1250
|
+
// -- mcp:restart (REPL-only) -----------------------------------------
|
|
1251
|
+
"mcp:restart": {
|
|
1252
|
+
name: "mcp:restart",
|
|
1253
|
+
title: "wstack mcp restart \u2014 restart a running MCP server (REPL only)",
|
|
1254
|
+
description: "Restart a single running MCP server by alias. This subcommand is only meaningful inside the REPL (`wstack` with no `<task>` argument) \u2014 from the top-level CLI it prints a warning and exits 0 because there's no live process to restart. Use the `/mcp restart <name>` slash command from inside the REPL.",
|
|
1255
|
+
usage: "wstack mcp restart <name> (REPL only)",
|
|
1256
|
+
seeAlso: "/mcp restart <name> (the in-REPL slash command); wstack mcp remove + wstack mcp add (replace the server config)"
|
|
1257
|
+
},
|
|
1258
|
+
// -- plugin (list / official) -----------------------------------------
|
|
1259
|
+
"plugin:list": {
|
|
1260
|
+
name: "plugin:list",
|
|
1261
|
+
title: "wstack plugin list \u2014 list configured plugins",
|
|
1262
|
+
description: "Print every plugin registered in the config, grouped by enabled vs disabled. Alias: `plugin status`. For the official registry (a curated list maintained by the WrongStack project), use `wstack plugin official` instead.",
|
|
1263
|
+
usage: "wstack plugin list (alias: wstack plugin status)",
|
|
1264
|
+
seeAlso: "wstack plugin official (curated registry); wstack plugin enable / disable (toggle state)"
|
|
1265
|
+
},
|
|
1266
|
+
"plugin:official": {
|
|
1267
|
+
name: "plugin:official",
|
|
1268
|
+
title: "wstack plugin official \u2014 list the curated official registry",
|
|
1269
|
+
description: "Print every plugin in the official registry (currently `telegram` and `lsp`). Each row shows the alias (for shorthand on the command line) and the full NPM specifier (what `wstack plugin add <spec>` actually installs). Aliases: `plugin officials` (plural).",
|
|
1270
|
+
usage: "wstack plugin official (alias: wstack plugin officials)",
|
|
1271
|
+
seeAlso: "wstack plugin add <alias> (install one); wstack plugin list (what you have)"
|
|
1272
|
+
},
|
|
1273
|
+
"plugin:officials": {
|
|
1274
|
+
// The plural form `plugin officials` is accepted as an
|
|
1275
|
+
// alias of `plugin official` in the underlying dispatch
|
|
1276
|
+
// (`plugin-management.ts`). The deep-help table mirrors
|
|
1277
|
+
// the alias so `wstack plugin officials --help` and
|
|
1278
|
+
// `wstack plugin official --help` both render the same
|
|
1279
|
+
// focused block.
|
|
1280
|
+
name: "plugin:officials",
|
|
1281
|
+
title: "wstack plugin officials \u2014 list the curated official registry (plural alias)",
|
|
1282
|
+
description: "Alias of `wstack plugin official`. Prints every plugin in the official registry. Same output as the singular form.",
|
|
1283
|
+
usage: "wstack plugin officials (plural alias of `wstack plugin official`)",
|
|
1284
|
+
seeAlso: "wstack plugin official (the singular form)"
|
|
1285
|
+
},
|
|
1286
|
+
// -- models (refresh + list) -----------------------------------------
|
|
1287
|
+
"models:refresh": {
|
|
1288
|
+
name: "models:refresh",
|
|
1289
|
+
title: "wstack models refresh \u2014 force-refresh the models.dev cache",
|
|
1290
|
+
description: "Re-fetch the models.dev catalog and replace the cached `models.json` in the global config dir. Useful when a new model is published mid-session and you want to see it in `wstack providers` / `wstack models` without restarting. The cache age is shown in the footer of every `wstack models` listing so you know when to refresh.",
|
|
1291
|
+
usage: "wstack models refresh",
|
|
1292
|
+
seeAlso: "wstack models <provider> (list models after refresh); wstack providers (force-refresh the provider catalog)"
|
|
1293
|
+
},
|
|
1294
|
+
"models:list": {
|
|
1295
|
+
name: "models:list",
|
|
1296
|
+
title: "wstack models list \u2014 list custom models registered locally",
|
|
1297
|
+
description: "Print every model that's been added via `wstack models add` (i.e. the entries in `config.json`'s `models` section, not the catalog). Distinct from `wstack models <provider>` which lists the catalog for a specific provider. The list is the audit surface for self-hosted / fine-tuned / overridden models.",
|
|
1298
|
+
usage: "wstack models list",
|
|
1299
|
+
seeAlso: "wstack models <provider> (catalog); wstack models add <mid> (register a custom model)"
|
|
1300
|
+
},
|
|
1301
|
+
// -- auth (list / status / remove) -------------------------------------
|
|
1302
|
+
// The top-level `wstack auth` entry in `helpTable` lists the
|
|
1303
|
+
// subcommands; these deep entries give each one its own focused
|
|
1304
|
+
// block so `wstack auth list --help`, `/help auth status`, and
|
|
1305
|
+
// `/auth status help` all render the same string the underlying
|
|
1306
|
+
// handler would emit. The descriptions match the actual
|
|
1307
|
+
// handler behavior in `packages/cli/src/subcommands/handlers/auth.ts`
|
|
1308
|
+
// — note that the `remove` subcommand is always interactive
|
|
1309
|
+
// (prompts for confirmation); the `[--force]` token in the
|
|
1310
|
+
// handler's error message is a documented hint that is not
|
|
1311
|
+
// yet wired up in the parser.
|
|
1312
|
+
"auth:list": {
|
|
1313
|
+
name: "auth:list",
|
|
1314
|
+
title: "wstack auth list \u2014 list saved providers and key status",
|
|
1315
|
+
description: "Read-only listing of every provider in the active profile config. Each provider block shows the family, baseUrl, model-allowlist size, and the saved API keys (the active key is marked with a green `\u25CF`, inactive keys with a dim `\u25CB`; all values are masked). Alias: `wstack auth ls`.",
|
|
1316
|
+
usage: "wstack auth list (alias: wstack auth ls)",
|
|
1317
|
+
subcommands: [
|
|
1318
|
+
{ name: "list", description: "List every saved provider (this command)." },
|
|
1319
|
+
{ name: "ls", description: "Alias of list." }
|
|
1320
|
+
],
|
|
1321
|
+
seeAlso: "wstack auth status <id> (detail for one provider); wstack auth remove <id> (delete one)"
|
|
1322
|
+
},
|
|
1323
|
+
"auth:status": {
|
|
1324
|
+
name: "auth:status",
|
|
1325
|
+
title: "wstack auth status <provider> \u2014 show detail for one provider",
|
|
1326
|
+
description: "Print the full `config.json` entry for a single provider: type, family, baseUrl, the `models` allowlist, the `envVars` list, and every saved key (active key marked with a green `\u25CF`, masked value, ISO timestamp). The provider id is required as a positional \u2014 `wstack auth status` with no id prints the usage hint and exits 1.",
|
|
1327
|
+
usage: "wstack auth status <provider>",
|
|
1328
|
+
subcommands: [
|
|
1329
|
+
{
|
|
1330
|
+
name: "<provider>",
|
|
1331
|
+
description: "The provider id to inspect (e.g. `openai`, `anthropic`)."
|
|
1332
|
+
}
|
|
1333
|
+
],
|
|
1334
|
+
seeAlso: "wstack auth list (find the id); wstack auth remove <id> (delete it); wstack auth (interactive edit)"
|
|
1335
|
+
},
|
|
1336
|
+
"auth:remove": {
|
|
1337
|
+
name: "auth:remove",
|
|
1338
|
+
title: "wstack auth remove <provider> \u2014 delete a provider and its keys",
|
|
1339
|
+
description: "Remove a provider entry and all its saved API keys from the active profile config. The flow is always interactive: after printing a confirmation prompt the handler waits for a `y` / `yes` answer (default `N`). The active session's in-memory provider is NOT reloaded \u2014 restart the REPL to fully tear down a running provider. Alias: `wstack auth rm`.",
|
|
1340
|
+
usage: "wstack auth remove <provider> (alias: wstack auth rm <provider>)",
|
|
1341
|
+
subcommands: [
|
|
1342
|
+
{ name: "<provider>", description: "The provider id to remove." },
|
|
1343
|
+
{ name: "rm", description: "Alias of remove." }
|
|
1344
|
+
],
|
|
1345
|
+
seeAlso: "wstack auth list (find the id); wstack auth status <id> (inspect before removing); wstack auth <provider> (re-add a different one)"
|
|
1346
|
+
},
|
|
1347
|
+
// The `auth:local` deep entry delegates its body to
|
|
1348
|
+
// `auth-local-help.ts` via the `customBody` field. The flag
|
|
1349
|
+
// list lives in exactly one place (`LOCAL_AUTH_FLAGS`), and
|
|
1350
|
+
// every surface that renders the help — `wstack auth local --help`,
|
|
1351
|
+
// `/auth local help`, `/help auth local` — produces the same
|
|
1352
|
+
// string. The `title` / `description` / `usage` / `seeAlso` fields
|
|
1353
|
+
// below are required by the `PerSubcommandHelp` shape but
|
|
1354
|
+
// never rendered (the `customBody` thunk owns the full layout).
|
|
1355
|
+
// They're filled in with sensible defaults so a future refactor
|
|
1356
|
+
// that drops `customBody` (e.g. to use the standard layout)
|
|
1357
|
+
// still has a coherent fallback.
|
|
1358
|
+
"auth:local": {
|
|
1359
|
+
name: "auth:local",
|
|
1360
|
+
title: "wstack auth local \u2014 quick-add Ollama / vLLM / LM Studio",
|
|
1361
|
+
description: "Pre-fills the base URL, runs a health probe, and persists the allowlist so you can `wstack --provider <id>` right away. Use `--no-probe` to skip the probe when the server is not running yet; `--audit <file>` captures the save lifecycle as JSONL.",
|
|
1362
|
+
usage: "wstack auth local [--name <id>] [--base-url <url>] [--no-key] [--no-probe|--probe-only] [--model <spec>] [--audit [target]]",
|
|
1363
|
+
seeAlso: "wstack auth (interactive menu); wstack auth <provider> (catalog add)",
|
|
1364
|
+
customBody: renderAuthLocalHelpToString
|
|
1365
|
+
},
|
|
1366
|
+
// -- bench (run — delegated to bench-run-help.ts via customBody) ------
|
|
1367
|
+
// The `bench:run` deep entry delegates its body to
|
|
1368
|
+
// `bench-run-help.ts` via the `customBody` field. The flag
|
|
1369
|
+
// list lives in exactly one place (`BENCH_RUN_FLAGS`), and
|
|
1370
|
+
// every surface that renders the help — `wstack bench run --help`,
|
|
1371
|
+
// `/bench run help`, `/help bench run` — produces the same
|
|
1372
|
+
// string. The `title` / `description` / `usage` / `seeAlso`
|
|
1373
|
+
// fields below are required by the `PerSubcommandHelp` shape
|
|
1374
|
+
// but never rendered (the `customBody` thunk owns the full
|
|
1375
|
+
// layout). They're filled in with sensible defaults so a
|
|
1376
|
+
// future refactor that drops `customBody` (e.g. to use the
|
|
1377
|
+
// standard layout) still has a coherent fallback.
|
|
1378
|
+
"bench:run": {
|
|
1379
|
+
name: "bench:run",
|
|
1380
|
+
title: "wstack bench run \u2014 execute a benchmark suite across a model matrix",
|
|
1381
|
+
description: "See renderBenchRunHelpToString() in bench-run-help.ts for the full block.",
|
|
1382
|
+
usage: "wstack bench run [...flags]",
|
|
1383
|
+
customBody: renderBenchRunHelpToString
|
|
1384
|
+
}
|
|
1385
|
+
};
|
|
1386
|
+
|
|
1387
|
+
// src/subcommands/handlers/per-subcommand-help-table.ts
|
|
1388
|
+
var helpTable = {
|
|
1389
|
+
init: {
|
|
1390
|
+
name: "init",
|
|
1391
|
+
title: "wstack init \u2014 DEPRECATED (use wstack auth)",
|
|
1392
|
+
description: "\u26A0 This command is deprecated. Use wstack auth for setup, key management, and model selection in one interactive workflow.",
|
|
1393
|
+
usage: "wstack init (deprecated)",
|
|
1394
|
+
seeAlso: "wstack auth (interactive setup + key manager)"
|
|
1395
|
+
},
|
|
1396
|
+
version: {
|
|
1397
|
+
name: "version",
|
|
1398
|
+
title: "wstack version \u2014 print the CLI version",
|
|
1399
|
+
description: "Prints the WrongStack CLI version, the apiVersion, the Node.js version, and the host platform. Useful for bug reports and CI logs.",
|
|
1400
|
+
usage: "wstack version"
|
|
1401
|
+
},
|
|
1402
|
+
mcp: {
|
|
1403
|
+
name: "mcp",
|
|
1404
|
+
title: "wstack mcp \u2014 manage Model Context Protocol servers",
|
|
1405
|
+
description: "List, add, remove, restart, and serve MCP servers registered in the global config. Servers are referenced by id and use the stdio, SSE, or streamable-HTTP transports.",
|
|
1406
|
+
usage: "wstack mcp [list|add|remove|restart|serve] [...]",
|
|
1407
|
+
subcommands: [
|
|
1408
|
+
{ name: "list", description: "List all configured MCP servers." },
|
|
1409
|
+
{ name: "add <id> <command>", description: "Register a new stdio MCP server." },
|
|
1410
|
+
{ name: "remove <id>", description: "Unregister an MCP server." },
|
|
1411
|
+
{ name: "restart <id>", description: "Restart a running MCP server." },
|
|
1412
|
+
{
|
|
1413
|
+
name: "serve",
|
|
1414
|
+
description: "Run the wstack MCP server; --resources/--prompts explicitly expose selected files."
|
|
1415
|
+
}
|
|
1416
|
+
],
|
|
1417
|
+
seeAlso: "wstack plugin (manage tool plugins similarly)"
|
|
1418
|
+
},
|
|
1419
|
+
plugin: {
|
|
1420
|
+
name: "plugin",
|
|
1421
|
+
title: "wstack plugin \u2014 manage tool plugins",
|
|
1422
|
+
description: "List, inspect, install, add, remove, enable, disable, and toggle tool plugins. Plugins extend the agent with custom tool packs (e.g. GitHub, Playwright, project-local helpers).",
|
|
1423
|
+
usage: "wstack plugin [list|status|report|menu|official|add|install|toggle|remove|enable|disable|manager] [...]",
|
|
1424
|
+
subcommands: [
|
|
1425
|
+
{ name: "list", description: "List installed plugins (alias: status)." },
|
|
1426
|
+
{ name: "report", description: "Show effective state, risk, and lock/toggle policy." },
|
|
1427
|
+
{ name: "menu", description: "Print the audit report outside the TUI plugin picker." },
|
|
1428
|
+
{ name: "official", description: "List plugins from the official registry." },
|
|
1429
|
+
{ name: "add <id>", description: "Add a plugin by id (alias: install)." },
|
|
1430
|
+
{ name: "toggle <id>", description: "Toggle a safe audit-list plugin row." },
|
|
1431
|
+
{ name: "remove <id>", description: "Remove an installed plugin (aliases: rm, uninstall)." },
|
|
1432
|
+
{ name: "enable <id>", description: "Re-enable a previously-disabled plugin." },
|
|
1433
|
+
{ name: "disable <id>", description: "Temporarily disable a plugin without removing it." },
|
|
1434
|
+
{
|
|
1435
|
+
name: "manager [lock|unlock] <id|*>",
|
|
1436
|
+
description: "Control whether the LLM may enable/disable individual plugins."
|
|
1437
|
+
}
|
|
1438
|
+
],
|
|
1439
|
+
seeAlso: "wstack mcp (MCP servers are registered as tool plugins)"
|
|
1440
|
+
},
|
|
1441
|
+
models: {
|
|
1442
|
+
name: "models",
|
|
1443
|
+
title: "wstack models \u2014 list and override models",
|
|
1444
|
+
description: "List models from the models.dev catalog, or override the default model for a provider with a custom id (for self-hosted or fine-tuned models not in the public catalog).",
|
|
1445
|
+
usage: "wstack models [<provider>] [add|remove|list|refresh] [...]",
|
|
1446
|
+
subcommands: [
|
|
1447
|
+
{ name: "<no-subcommand>", description: "List models for the default provider." },
|
|
1448
|
+
{ name: "<provider>", description: "List models for a specific provider." },
|
|
1449
|
+
{
|
|
1450
|
+
name: "add <mid>",
|
|
1451
|
+
description: "Add or override a custom model (--max-context, --tools, --vision, \u2026)."
|
|
1452
|
+
},
|
|
1453
|
+
{ name: "remove <mid>", description: "Remove a custom model." },
|
|
1454
|
+
{ name: "list", description: "List all custom models registered locally." },
|
|
1455
|
+
{ name: "refresh", description: "Force-refresh the models.dev cache." }
|
|
1456
|
+
],
|
|
1457
|
+
seeAlso: "wstack providers (list provider families and their defaults)"
|
|
1458
|
+
},
|
|
1459
|
+
config: {
|
|
1460
|
+
name: "config",
|
|
1461
|
+
title: "wstack config \u2014 show or edit effective config",
|
|
1462
|
+
description: "Print the resolved config (with the on-disk overrides merged on top), or open the active profile config in $EDITOR for interactive edits. Also exposes a small audit log of recent config-history changes for diagnostics.",
|
|
1463
|
+
usage: "wstack config [show|edit|history|restore] [...]",
|
|
1464
|
+
subcommands: [
|
|
1465
|
+
{ name: "show", description: "Print the resolved config to stdout (default)." },
|
|
1466
|
+
{ name: "edit", description: "Open the active profile config in $EDITOR." },
|
|
1467
|
+
{ name: "history", description: "List recent config-history entries." },
|
|
1468
|
+
{ name: "restore <id>", description: "Restore a previous config-history entry." }
|
|
1469
|
+
],
|
|
1470
|
+
seeAlso: "wstack auth (most config edits are auth/key changes)"
|
|
1471
|
+
},
|
|
1472
|
+
// -- API key / auth management -----------------------------------------
|
|
1473
|
+
auth: {
|
|
1474
|
+
name: "auth",
|
|
1475
|
+
title: "wstack auth \u2014 manage API keys and provider credentials",
|
|
1476
|
+
description: "Add, view, and remove provider API keys. The interactive menu supports a custom-URL path for self-hosted / local servers, a quick-shortcut path for Ollama / vLLM / LM Studio, and a catalog path for the well-known providers.",
|
|
1477
|
+
usage: "wstack auth [list|status|remove] [...] | wstack auth <provider> | wstack auth local [...]",
|
|
1478
|
+
subcommands: [
|
|
1479
|
+
{ name: "list", description: "List saved providers and key status." },
|
|
1480
|
+
{ name: "status <id>", description: "Show detail for one provider." },
|
|
1481
|
+
{ name: "remove <id>", description: "Remove a provider and its keys." },
|
|
1482
|
+
{ name: "<provider>", description: "Add a key for a named provider (--label, --family, \u2026)." },
|
|
1483
|
+
{
|
|
1484
|
+
name: "local",
|
|
1485
|
+
description: "Pre-fill Ollama / vLLM / LM Studio (--name, --base-url, --no-probe, --model, --audit \u2026)."
|
|
1486
|
+
},
|
|
1487
|
+
{
|
|
1488
|
+
name: "login <chatgpt|claude|copilot>",
|
|
1489
|
+
description: "Subscription OAuth login: chatgpt (\u2192 openai-codex), claude (\u2192 anthropic-oauth), or copilot (\u2192 github-copilot). Opens browser; no API key. \u26A0 Using subscriptions outside official clients may violate provider ToS (account ban risk); an API key is the sanctioned path."
|
|
1490
|
+
}
|
|
1491
|
+
],
|
|
1492
|
+
seeAlso: "wstack auth local (pre-fill Ollama / vLLM / LM Studio)"
|
|
1493
|
+
},
|
|
1494
|
+
// -- Session list / resume / show / fork --------------------------------
|
|
1495
|
+
sessions: {
|
|
1496
|
+
name: "sessions",
|
|
1497
|
+
title: "wstack sessions \u2014 list and resume recent sessions",
|
|
1498
|
+
description: "List recent sessions, show one session in detail, resume a session, or inspect a session's audit log. The audit log is stored as JSONL next to each session's recording.",
|
|
1499
|
+
usage: "wstack sessions [list|show|resume|fork|config|fleet] [...]",
|
|
1500
|
+
subcommands: [
|
|
1501
|
+
{ name: "list", description: "List the most recent sessions." },
|
|
1502
|
+
{ name: "show <id>", description: "Show one session in detail." },
|
|
1503
|
+
{ name: "resume [<id>]", description: "Resume a session (latest if no id given)." },
|
|
1504
|
+
{
|
|
1505
|
+
name: "fork [<id>] [--to N]",
|
|
1506
|
+
description: "Create an isolated child journal at a persisted boundary."
|
|
1507
|
+
},
|
|
1508
|
+
{ name: "config", description: "Show or edit session-specific config." },
|
|
1509
|
+
{ name: "fleet", description: "List the active fleet of sessions." }
|
|
1510
|
+
],
|
|
1511
|
+
seeAlso: "wstack audit (the session-level audit log reader)"
|
|
1512
|
+
},
|
|
1513
|
+
// -- Diagnostics --------------------------------------------------------
|
|
1514
|
+
doctor: {
|
|
1515
|
+
name: "doctor",
|
|
1516
|
+
title: "wstack doctor \u2014 health checks",
|
|
1517
|
+
description: "Run a series of health checks (provider + key + models cache + secret vault + sessions dir + MCP server config) and exit non-zero if any check fails. Use as a CI gate or a post-install smoke test. With --daemons, inspect this project\u2019s IPC daemons instead: each is reported live, stale, or stopped. A stale endpoint is one whose owner died without releasing it; daemons reclaim it on their next start, or --clear-stale removes it now. Listing never spawns a daemon.",
|
|
1518
|
+
usage: "wstack doctor [--daemons [--clear-stale]]",
|
|
1519
|
+
seeAlso: "wstack diag (read-only environment dump for bug reports)"
|
|
1520
|
+
},
|
|
1521
|
+
diag: {
|
|
1522
|
+
name: "diag",
|
|
1523
|
+
title: "wstack diag \u2014 read-only environment dump",
|
|
1524
|
+
description: "Print a key=value environment snapshot (apiVersion, cwd, project info, paths, cache age, configured provider + model, tool/plugin counts, MCP server count). Never modifies state \u2014 safe to paste into bug reports.",
|
|
1525
|
+
usage: "wstack diag",
|
|
1526
|
+
seeAlso: "wstack doctor (pass/fail health checks vs. this is a dump)"
|
|
1527
|
+
},
|
|
1528
|
+
// -- Session audit / replay / rewind -----------------------------------
|
|
1529
|
+
audit: {
|
|
1530
|
+
name: "audit",
|
|
1531
|
+
title: "wstack audit \u2014 inspect a session's tamper-evident audit log",
|
|
1532
|
+
description: "Show the chained-hash entries for a recorded session and run a verification pass to surface any post-hoc modification. Each entry is SHA-256-chained to the previous; any tampering breaks the chain and is reported.",
|
|
1533
|
+
usage: "wstack audit [<sessionId>] [--list]",
|
|
1534
|
+
subcommands: [
|
|
1535
|
+
{ name: "<sessionId>", description: "Show entries + verify chain (positional)." },
|
|
1536
|
+
{ name: "--list / -l", description: "List every session that has an audit log." }
|
|
1537
|
+
],
|
|
1538
|
+
seeAlso: "wstack replay (the corresponding provider-response log)"
|
|
1539
|
+
},
|
|
1540
|
+
replay: {
|
|
1541
|
+
name: "replay",
|
|
1542
|
+
title: "wstack replay \u2014 inspect a session's recorded provider responses",
|
|
1543
|
+
description: "Show the recorded request/response pairs for a session \u2014 the frozen inputs the agent saw, in order. This is the inspection surface; to actually re-run the agent with those responses, use `wstack --replay <sessionId>`.",
|
|
1544
|
+
usage: "wstack replay [<sessionId>] [--list]",
|
|
1545
|
+
subcommands: [
|
|
1546
|
+
{ name: "<sessionId>", description: "Show the recorded entries (positional)." },
|
|
1547
|
+
{ name: "--list / -l", description: "List every session that has a replay log." }
|
|
1548
|
+
],
|
|
1549
|
+
seeAlso: "wstack audit (the tamper-evident tool-call log)"
|
|
1550
|
+
},
|
|
1551
|
+
rewind: {
|
|
1552
|
+
name: "rewind",
|
|
1553
|
+
title: "wstack rewind \u2014 rewind a session to an earlier state",
|
|
1554
|
+
description: "Restore a session's in-memory state to a previous point in its recording. The rewind is non-destructive: the original session is preserved, and a new resumed session picks up from the rewound point. Useful for re-running a fork of an exploration without losing the original.",
|
|
1555
|
+
usage: "wstack rewind [<sessionId>] [--all|--last <n>|--to <id>] [--list] [--resume]",
|
|
1556
|
+
subcommands: [
|
|
1557
|
+
{ name: "<sessionId>", description: "Session id (positional; defaults to the latest)." },
|
|
1558
|
+
{ name: "--all", description: "Rewind to the start of the session." },
|
|
1559
|
+
{ name: "--last <n>", description: "Rewind to `n` steps back from the end." },
|
|
1560
|
+
{ name: "--to <id>", description: "Rewind to a specific step id." },
|
|
1561
|
+
{ name: "--list", description: "List available rewind points for the session." },
|
|
1562
|
+
{ name: "--resume", description: "Resume the rewound session after the rewind." }
|
|
1563
|
+
],
|
|
1564
|
+
seeAlso: "wstack replay (the underlying provider-response log)"
|
|
1565
|
+
},
|
|
1566
|
+
// -- Export & usage ----------------------------------------------------
|
|
1567
|
+
export: {
|
|
1568
|
+
name: "export",
|
|
1569
|
+
title: "wstack export \u2014 render a session to a portable format",
|
|
1570
|
+
description: "Render a recorded session to Markdown, JSON, or plain text. Use Markdown for human-readable share/audit artifacts, JSON for downstream tooling, or text for grep-friendly search. Tools and diagnostics are included by default; toggle either off with `--no-tools` or `--no-diagnostics`.",
|
|
1571
|
+
usage: "wstack export <sessionId> [--format markdown|json|text] [--out <file>] [--no-tools] [--no-diagnostics]",
|
|
1572
|
+
subcommands: [
|
|
1573
|
+
{ name: "<sessionId>", description: "The session id to render (positional)." },
|
|
1574
|
+
{
|
|
1575
|
+
name: "--format <f> / -f <f>",
|
|
1576
|
+
description: "Output format: markdown (default), json, or text."
|
|
1577
|
+
},
|
|
1578
|
+
{ name: "--out <file> / -o <file>", description: "Write to <file> instead of stdout." },
|
|
1579
|
+
{ name: "--no-tools", description: "Omit tool-call entries from the output." },
|
|
1580
|
+
{
|
|
1581
|
+
name: "--no-diagnostics",
|
|
1582
|
+
description: "Omit diagnostic entries (errors, retries) from the output."
|
|
1583
|
+
}
|
|
1584
|
+
],
|
|
1585
|
+
seeAlso: "wstack replay (the recorded provider-response log)"
|
|
1586
|
+
},
|
|
1587
|
+
usage: {
|
|
1588
|
+
name: "usage",
|
|
1589
|
+
title: "wstack usage \u2014 token + cost summary",
|
|
1590
|
+
description: "Print a per-session token + cost summary from the audit log. Useful for cost reviews and the post-session billing recap. Aggregates input/output tokens and the per-model cost; requires the session to have been recorded with audit enabled.",
|
|
1591
|
+
usage: "wstack usage",
|
|
1592
|
+
seeAlso: "wstack export (full session render for archival)"
|
|
1593
|
+
},
|
|
1594
|
+
// -- Listing subcommands -----------------------------------------------
|
|
1595
|
+
providers: {
|
|
1596
|
+
name: "providers",
|
|
1597
|
+
title: "wstack providers \u2014 list providers from models.dev",
|
|
1598
|
+
description: "List provider families from the live models.dev catalog. Default view shows the popular three (Anthropic, OpenAI, Google); pass `--all` to include every supported family, or `--unsupported` to surface the ones without a built-in transport (which require a plugin).",
|
|
1599
|
+
usage: "wstack providers [--all] [--unsupported]",
|
|
1600
|
+
subcommands: [
|
|
1601
|
+
{ name: "--all", description: "Include every supported family, not just the popular three." },
|
|
1602
|
+
{
|
|
1603
|
+
name: "--unsupported",
|
|
1604
|
+
description: "Include families without a built-in transport (need a plugin)."
|
|
1605
|
+
}
|
|
1606
|
+
],
|
|
1607
|
+
seeAlso: "wstack models (list models within a provider)"
|
|
1608
|
+
},
|
|
1609
|
+
tools: {
|
|
1610
|
+
name: "tools",
|
|
1611
|
+
title: "wstack tools \u2014 list registered tools",
|
|
1612
|
+
description: "List every tool the agent can invoke, with its owner (built-in / plugin) and permission level. Useful for auditing what a session can do, especially after installing a new plugin.",
|
|
1613
|
+
usage: "wstack tools",
|
|
1614
|
+
seeAlso: "wstack skills (list skills; tools + skills are the two extension surfaces)"
|
|
1615
|
+
},
|
|
1616
|
+
skills: {
|
|
1617
|
+
name: "skills",
|
|
1618
|
+
title: "wstack skills \u2014 list discovered skills",
|
|
1619
|
+
description: "List every skill the agent can invoke, grouped by source (bundled / user-installed / project-local). Skills are on-demand context packs that load only when triggered.",
|
|
1620
|
+
usage: "wstack skills",
|
|
1621
|
+
seeAlso: "wstack tools (tools are always-loaded; skills are on-demand)"
|
|
1622
|
+
},
|
|
1623
|
+
projects: {
|
|
1624
|
+
name: "projects",
|
|
1625
|
+
title: "wstack projects \u2014 list tracked projects",
|
|
1626
|
+
description: "List every project WrongStack has seen (tracked by a hashed root). Each entry shows the project root and the last-seen timestamp. Useful for cleaning up the global projects dir after a workspace migration.",
|
|
1627
|
+
usage: "wstack projects"
|
|
1628
|
+
},
|
|
1629
|
+
// -- Lifecycle ---------------------------------------------------------
|
|
1630
|
+
update: {
|
|
1631
|
+
name: "update",
|
|
1632
|
+
title: "wstack update \u2014 self-update the CLI",
|
|
1633
|
+
description: "Check the latest npm version and update the globally-installed `wrongstack` package. Use `--check-only` to just print the current/latest without installing. The update is global; run from any project root.",
|
|
1634
|
+
usage: "wstack update [--check-only]",
|
|
1635
|
+
seeAlso: "wstack version (read-only version info)"
|
|
1636
|
+
},
|
|
1637
|
+
// -- ACP (Agent Client Protocol) --------------------------------------
|
|
1638
|
+
acp: {
|
|
1639
|
+
name: "acp",
|
|
1640
|
+
title: "wstack acp \u2014 Agent Client Protocol (ACP) integration",
|
|
1641
|
+
description: "Run WrongStack as an ACP server (stdio) for editor clients (Zed, JetBrains, VS Code ACP), or orchestrate external ACP agents through spawn, probe, bench, and parallel fan-out.",
|
|
1642
|
+
usage: "wstack acp [server|list|sync|spawn|parallel|probe|bench] [...]",
|
|
1643
|
+
subcommands: [
|
|
1644
|
+
{ name: "server / serve", description: "Start WrongStack as an ACP stdio server (default)." },
|
|
1645
|
+
{ name: "list", description: "List available ACP agents from the cache." },
|
|
1646
|
+
{ name: "sync", description: "Sync the official ACP agent registry into local cache." },
|
|
1647
|
+
{ name: "spawn <id> <task>", description: "Spawn an ACP agent and wait for results." },
|
|
1648
|
+
{ name: "parallel <csv> <task>", description: "Fan a task out to multiple ACP agents in parallel." },
|
|
1649
|
+
{ name: "probe [csv]", description: "Handshake-test installed ACP agents." },
|
|
1650
|
+
{ name: "bench [csv] [--fs]", description: "End-to-end benchmark and grade ACP agents." }
|
|
1651
|
+
],
|
|
1652
|
+
seeAlso: "wstack mcp serve (the MCP equivalent; pick the protocol your client speaks)"
|
|
1653
|
+
},
|
|
1654
|
+
// -- Model diagnostics (read-only) -----------------------------------
|
|
1655
|
+
modeldiag: {
|
|
1656
|
+
name: "modeldiag",
|
|
1657
|
+
title: "wstack modeldiag \u2014 model benchmarks + heuristic diagnostics",
|
|
1658
|
+
description: "Read-only diagnostics for the configured model: key check, capability scan (vision / tools / context window), heuristic strengths/weaknesses (bestFor / avoidFor), sequential live provider/model smoke tests, and real benchmarks against a small prompt suite. Smoke tests use tiny prompts and never print credentials.",
|
|
1659
|
+
usage: "wstack modeldiag [test|eval] [...]",
|
|
1660
|
+
subcommands: [
|
|
1661
|
+
{
|
|
1662
|
+
name: "<no subcommand>",
|
|
1663
|
+
description: "Print configured model capabilities, context limits, and recommendations."
|
|
1664
|
+
},
|
|
1665
|
+
{
|
|
1666
|
+
name: "test [--plan|--all-models|--json]",
|
|
1667
|
+
description: "Run live sequential smoke tests across configured models."
|
|
1668
|
+
},
|
|
1669
|
+
{
|
|
1670
|
+
name: "eval [--providers <csv>]",
|
|
1671
|
+
description: "Run model competency matrix evaluation across tasks."
|
|
1672
|
+
}
|
|
1673
|
+
],
|
|
1674
|
+
seeAlso: "wstack modeldiag test --plan; wstack modeldiag test; wstack modeldiag test --all-models"
|
|
1675
|
+
},
|
|
1676
|
+
// -- Bench (developer / CI only) -------------------------------------
|
|
1677
|
+
bench: {
|
|
1678
|
+
name: "bench",
|
|
1679
|
+
title: "wstack bench \u2014 run model-independent agentic benchmarks",
|
|
1680
|
+
description: "Run WrongStack against the Aider polyglot or SWE-bench Verified suites with deterministic graders. Used internally to compare model quality across releases; also useful for evaluating a new model before adopting it.",
|
|
1681
|
+
usage: "wstack bench [run|report|list] [...]",
|
|
1682
|
+
subcommands: [
|
|
1683
|
+
{ name: "run", description: "Run a benchmark suite (--suite <id> --models <config>)." },
|
|
1684
|
+
{ name: "report <dir>", description: "Render the Markdown report for a prior run." },
|
|
1685
|
+
{ name: "list", description: "List available suites and the model configs in the catalog." }
|
|
1686
|
+
],
|
|
1687
|
+
seeAlso: "wstack modeldiag (read-only diagnostics; bench actually runs the model)"
|
|
1688
|
+
},
|
|
1689
|
+
// -- Quick launch ------------------------------------------------------
|
|
1690
|
+
quick: {
|
|
1691
|
+
name: "quick",
|
|
1692
|
+
title: "wstack quick \u2014 launch the TUI with sensible defaults",
|
|
1693
|
+
description: "Accept every default, list installed plugins, and open the TUI with the agents-monitor panel pre-shown. Equivalent to `wstack --tui --quick`; the dedicated subcommand is for discoverability and tab-completion. The actual TUI launch is intercepted in `boot()` before this handler runs.",
|
|
1694
|
+
usage: "wstack quick",
|
|
1695
|
+
seeAlso: "wstack --tui (the underlying flag; quick is just a shortcut)"
|
|
1696
|
+
},
|
|
1697
|
+
// -- Aliases and meta commands ───────────────────────────────────────
|
|
1698
|
+
plugins: {
|
|
1699
|
+
name: "plugins",
|
|
1700
|
+
title: "wstack plugins \u2014 alias for wstack plugin",
|
|
1701
|
+
description: "Alias for `wstack plugin`. See `wstack plugin --help` for the full set of subcommands.",
|
|
1702
|
+
usage: "wstack plugins (alias for wstack plugin)",
|
|
1703
|
+
seeAlso: "wstack plugin (the canonical command)"
|
|
1704
|
+
},
|
|
1705
|
+
help: {
|
|
1706
|
+
name: "help",
|
|
1707
|
+
title: "wstack help \u2014 print top-level help",
|
|
1708
|
+
description: "Print the top-level help text listing every subcommand with a one-line summary. Equivalent to `wstack --help`.",
|
|
1709
|
+
usage: "wstack help",
|
|
1710
|
+
seeAlso: "wstack --help"
|
|
1711
|
+
},
|
|
1712
|
+
// -- HQ (dashboard server) ──────────────────────────────────────────
|
|
1713
|
+
hq: {
|
|
1714
|
+
name: "hq",
|
|
1715
|
+
title: "wstack hq \u2014 start HQ command center or manage tokens",
|
|
1716
|
+
description: "Start the HQ server \u2014 a web dashboard for monitoring sessions, fleet status, and agent activity across projects \u2014 or manage browser and client authentication tokens.",
|
|
1717
|
+
usage: "wstack hq [serve] [--port <n>] [--password <secret>] [--tunnel] [--open] | wstack hq token [create|list|revoke]",
|
|
1718
|
+
subcommands: [
|
|
1719
|
+
{ name: "serve", description: "Start the HQ dashboard server (default)." },
|
|
1720
|
+
{ name: "token create [label]", description: "Mint a browser or client authentication token." },
|
|
1721
|
+
{ name: "token list", description: "List active HQ authentication tokens." },
|
|
1722
|
+
{ name: "token revoke <id>", description: "Revoke an issued HQ authentication token." }
|
|
1723
|
+
],
|
|
1724
|
+
seeAlso: "wstack sessions fleet (CLI equivalent for fleet status)"
|
|
1725
|
+
},
|
|
1726
|
+
// -- Mailbox (external agent bridge) ────────────────────────────────
|
|
1727
|
+
mailbox: {
|
|
1728
|
+
name: "mailbox",
|
|
1729
|
+
title: "wstack mailbox \u2014 serve the external-agent mailbox HTTP bridge",
|
|
1730
|
+
description: "Start the mailbox HTTP bridge that lets external coding agents (Claude Code, Aider, custom scripts) communicate with the shared project mailbox. The server exposes a REST + SSE API for sending, checking, and acknowledging messages. Use `wstack mailbox serve` to start the listener.",
|
|
1731
|
+
usage: "wstack mailbox serve [--port <n>]",
|
|
1732
|
+
subcommands: [{ name: "serve", description: "Start the mailbox HTTP bridge listener." }],
|
|
1733
|
+
seeAlso: "wstack hq (the HQ server includes mailbox routing)"
|
|
1734
|
+
},
|
|
1735
|
+
// -- Permissions ────────────────────────────────────────────────────
|
|
1736
|
+
permissions: {
|
|
1737
|
+
name: "permissions",
|
|
1738
|
+
title: "wstack permissions \u2014 explain tool permission decisions",
|
|
1739
|
+
description: "Side-effect-free permission decision explainer. Evaluates the effective permission rules for a tool and input arguments without prompting, modifying trust files, or mutating state.",
|
|
1740
|
+
usage: "wstack permissions explain <tool> [--input '<json>'] [--json]",
|
|
1741
|
+
subcommands: [
|
|
1742
|
+
{
|
|
1743
|
+
name: "explain <tool>",
|
|
1744
|
+
description: "Explain how the permission policy evaluates a tool call."
|
|
1745
|
+
}
|
|
1746
|
+
],
|
|
1747
|
+
seeAlso: "wstack tools (list available tools)"
|
|
1748
|
+
},
|
|
1749
|
+
// -- Project management ─────────────────────────────────────────────
|
|
1750
|
+
project: {
|
|
1751
|
+
name: "project",
|
|
1752
|
+
title: "wstack project \u2014 manage committed repository identity",
|
|
1753
|
+
description: "Manage the committed repository identity (project.json) used to scope HQ dashboards, Kanban state, and multi-agent coordination. Commit the generated ID file so every clone shares the same project.",
|
|
1754
|
+
usage: "wstack project [id|init|rekey] [--yes]",
|
|
1755
|
+
subcommands: [
|
|
1756
|
+
{ name: "id", description: "Show the current project ID and config path (default)." },
|
|
1757
|
+
{ name: "init", description: "Initialize a project ID if not already present." },
|
|
1758
|
+
{ name: "rekey", description: "Generate a new project ID for a fork (requires --yes)." }
|
|
1759
|
+
],
|
|
1760
|
+
seeAlso: "wstack projects (list all tracked projects)"
|
|
1761
|
+
},
|
|
1762
|
+
governance: {
|
|
1763
|
+
name: "governance",
|
|
1764
|
+
title: "wstack governance \u2014 inspect deterministic project-daemon health",
|
|
1765
|
+
description: "Read token-free attachment-broker health from the current project daemon. Warnings are advisory: they surface deterministic operator escalation signals without stopping active tasks or model execution.",
|
|
1766
|
+
usage: "wstack governance status [--json]",
|
|
1767
|
+
subcommands: [{ name: "status", description: "Show daemon and attachment-broker health." }],
|
|
1768
|
+
seeAlso: "wstack doctor (broader environment diagnostics)"
|
|
1769
|
+
},
|
|
1770
|
+
// -- Chronicle ──────────────────────────────────────────────────────
|
|
1771
|
+
chronicle: {
|
|
1772
|
+
name: "chronicle",
|
|
1773
|
+
title: "wstack chronicle \u2014 query cross-session provenance ledger",
|
|
1774
|
+
description: "Query the cross-session event ledger, inspect daemon status, compute facet aggregations, view token/cost metrics, or purge old retention entries.",
|
|
1775
|
+
usage: "wstack chronicle [query|status|facet|metrics|prune|compact] [...]",
|
|
1776
|
+
subcommands: [
|
|
1777
|
+
{ name: "query [field=value ...]", description: "Query recorded provenance events." },
|
|
1778
|
+
{ name: "status", description: "Check the Chronicle daemon and pipeline status." },
|
|
1779
|
+
{ name: "facet <field>", description: "Group and count events across a facet." },
|
|
1780
|
+
{ name: "metrics [providers|tasks|files|summary]", description: "Query aggregated metrics from metrics.db." },
|
|
1781
|
+
{ name: "prune [--days N] [--dry-run]", description: "Purge journal entries older than N days." },
|
|
1782
|
+
{ name: "compact", description: "Defragment and compact SQLite ledger." }
|
|
1783
|
+
],
|
|
1784
|
+
seeAlso: "wstack audit (per-session audit log); wstack usage (cost summary)"
|
|
1785
|
+
}
|
|
1786
|
+
};
|
|
1787
|
+
|
|
1788
|
+
// src/subcommands/handlers/per-subcommand-help.ts
|
|
1789
|
+
var COLUMN_WIDTH = 28;
|
|
1790
|
+
function renderBlockToString(help) {
|
|
1791
|
+
if (help.customBody) {
|
|
1792
|
+
return help.customBody();
|
|
1793
|
+
}
|
|
1794
|
+
const lines = [
|
|
1795
|
+
color5.bold(help.title),
|
|
1796
|
+
color5.dim(` ${help.description}`),
|
|
1797
|
+
"",
|
|
1798
|
+
color5.bold("Usage"),
|
|
1799
|
+
` ${help.usage}`
|
|
1800
|
+
];
|
|
1801
|
+
if (help.subcommands && help.subcommands.length > 0) {
|
|
1802
|
+
lines.push("");
|
|
1803
|
+
lines.push(color5.bold("Subcommands"));
|
|
1804
|
+
for (const { name, description } of help.subcommands) {
|
|
1805
|
+
const padded = name.padEnd(COLUMN_WIDTH, " ");
|
|
1806
|
+
lines.push(` ${color5.cyan(padded)}${description}`);
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
if (help.seeAlso) {
|
|
1810
|
+
lines.push("");
|
|
1811
|
+
lines.push(color5.dim(` See also: ${help.seeAlso}`));
|
|
1812
|
+
}
|
|
1813
|
+
lines.push("");
|
|
1814
|
+
lines.push(color5.dim(" Tip: `wstack --help` lists every top-level command."));
|
|
1815
|
+
return lines.join("\n") + "\n";
|
|
1816
|
+
}
|
|
1817
|
+
function renderBlock(help, renderer) {
|
|
1818
|
+
renderer.write(renderBlockToString(help));
|
|
1819
|
+
}
|
|
1820
|
+
function renderDeepHelp(key, renderer) {
|
|
1821
|
+
const help = deepHelpTable[key];
|
|
1822
|
+
if (!help) return false;
|
|
1823
|
+
renderBlock(help, renderer);
|
|
1824
|
+
return true;
|
|
1825
|
+
}
|
|
1826
|
+
var deepSubcommandsWithFocusedHelp = Object.keys(deepHelpTable);
|
|
1827
|
+
function renderFocusedHelp(subcommand, renderer) {
|
|
1828
|
+
const help = helpTable[subcommand];
|
|
1829
|
+
if (!help) return false;
|
|
1830
|
+
renderBlock(help, renderer);
|
|
1831
|
+
return true;
|
|
1832
|
+
}
|
|
1833
|
+
var subcommandsWithFocusedHelp = Object.keys(helpTable);
|
|
1834
|
+
|
|
717
1835
|
// src/subcommands/index.ts
|
|
718
1836
|
var loaders = {
|
|
719
1837
|
acp: async () => (await import("./acp-5ZLGFHWP.js")).acpCmd,
|
|
720
1838
|
init: async () => (await import("./init-E2NDDOHI.js")).initCmd,
|
|
721
|
-
auth: async () => (await import("./auth-
|
|
1839
|
+
auth: async () => (await import("./auth-TVOOHL4Q.js")).authCmd,
|
|
722
1840
|
update: async () => (await import("./update-VZSOZGYC.js")).updateCmd,
|
|
723
1841
|
sessions: async () => (await import("./sessions-config-YX2ZPAFM.js")).sessionsCmd,
|
|
724
1842
|
config: async () => (await import("./sessions-config-YX2ZPAFM.js")).configCmd,
|
|
@@ -727,23 +1845,23 @@ var loaders = {
|
|
|
727
1845
|
audit: async () => (await import("./audit-BBR22QH3.js")).auditCmd,
|
|
728
1846
|
tools: async () => (await import("./tools-skills-UNKLOB7M.js")).toolsCmd,
|
|
729
1847
|
skills: async () => (await import("./tools-skills-UNKLOB7M.js")).skillsCmd,
|
|
730
|
-
providers: async () => (await import("./providers-models-
|
|
731
|
-
models: async () => (await import("./providers-models-
|
|
732
|
-
mcp: async () => (await import("./mcp-
|
|
1848
|
+
providers: async () => (await import("./providers-models-4FAKM2WO.js")).providersCmd,
|
|
1849
|
+
models: async () => (await import("./providers-models-4FAKM2WO.js")).modelsCmd,
|
|
1850
|
+
mcp: async () => (await import("./mcp-CMLFHRG2.js")).mcpCmd,
|
|
733
1851
|
plugin: async () => (await import("./plugin-usage-PTEETL3J.js")).pluginCmd,
|
|
734
1852
|
plugins: async () => (await import("./plugin-usage-PTEETL3J.js")).pluginCmd,
|
|
735
1853
|
diag: async () => (await import("./diag-doctor-WTBHPOMB.js")).diagCmd,
|
|
736
1854
|
doctor: async () => (await import("./diag-doctor-WTBHPOMB.js")).doctorCmd,
|
|
737
1855
|
export: async () => (await import("./export-CCUXRJOU.js")).exportCmd,
|
|
738
1856
|
usage: async () => (await import("./plugin-usage-PTEETL3J.js")).usageCmd,
|
|
739
|
-
version: async () => (await import("./version-help-
|
|
740
|
-
help: async () => (await import("./version-help-
|
|
1857
|
+
version: async () => (await import("./version-help-TFD6VPF3.js")).versionCmd,
|
|
1858
|
+
help: async () => (await import("./version-help-TFD6VPF3.js")).helpCmd,
|
|
741
1859
|
projects: async () => (await import("./projects-XE76NFNZ.js")).projectsCmd,
|
|
742
|
-
modeldiag: async () => (await import("./modeldiag-
|
|
1860
|
+
modeldiag: async () => (await import("./modeldiag-ICMPHT5L.js")).modeldiagCmd,
|
|
743
1861
|
quick: async () => (await import("./quick-VIO2BEHS.js")).quickCmd,
|
|
744
1862
|
bench: async () => (await import("./bench-XNDUJOSZ.js")).benchCmd,
|
|
745
1863
|
chronicle: async () => (await import("./chronicle-63MFCZN6.js")).chronicleCmd,
|
|
746
|
-
hq: async () => (await import("./hq-
|
|
1864
|
+
hq: async () => (await import("./hq-PA6RH2UW.js")).hqCmd,
|
|
747
1865
|
mailbox: async () => (await import("./mailbox-serve-V3QIJBDH.js")).mailboxServeCmd,
|
|
748
1866
|
permissions: async () => (await import("./permissions-2PWBL4YU.js")).permissionsCmd,
|
|
749
1867
|
project: async () => (await import("./project-BLQ3ALVL.js")).projectCmd,
|
|
@@ -763,16 +1881,28 @@ async function handleHelpVersionShortCircuit(argv) {
|
|
|
763
1881
|
if (earlyFlags["help"] !== true && earlyFlags["version"] !== true) {
|
|
764
1882
|
return null;
|
|
765
1883
|
}
|
|
766
|
-
if (earlyFlags["help"] === true && positional.length > 0 && subcommandNames.includes(positional[0])) {
|
|
767
|
-
return null;
|
|
768
|
-
}
|
|
769
1884
|
const stubRenderer = {
|
|
770
1885
|
write: (line) => {
|
|
771
1886
|
process.stdout.write(line);
|
|
772
1887
|
}
|
|
773
1888
|
};
|
|
774
|
-
|
|
775
|
-
|
|
1889
|
+
if (earlyFlags["version"] === true) {
|
|
1890
|
+
return await versionCmd([], { renderer: stubRenderer });
|
|
1891
|
+
}
|
|
1892
|
+
if (earlyFlags["help"] === true) {
|
|
1893
|
+
if (positional.length > 0 && subcommandNames.includes(positional[0])) {
|
|
1894
|
+
const first = positional[0];
|
|
1895
|
+
const deep = positional[1];
|
|
1896
|
+
if (deep && renderDeepHelp(`${first}:${deep}`, stubRenderer)) {
|
|
1897
|
+
return 0;
|
|
1898
|
+
}
|
|
1899
|
+
if (renderFocusedHelp(first, stubRenderer)) {
|
|
1900
|
+
return 0;
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
return await helpCmd([], { renderer: stubRenderer });
|
|
1904
|
+
}
|
|
1905
|
+
return null;
|
|
776
1906
|
}
|
|
777
1907
|
|
|
778
1908
|
// src/boot/short-circuit-hq.ts
|
|
@@ -783,7 +1913,7 @@ import {
|
|
|
783
1913
|
readHqRuntimeFileSync,
|
|
784
1914
|
resolveHqDataDir
|
|
785
1915
|
} from "@wrongstack/core/hq";
|
|
786
|
-
import { color as
|
|
1916
|
+
import { color as color6, isPidAlive } from "@wrongstack/core/utils";
|
|
787
1917
|
async function isHqAlreadyRunning(dataDir) {
|
|
788
1918
|
const marker = readHqRuntimeFileSync(dataDir);
|
|
789
1919
|
if (!marker) return null;
|
|
@@ -808,12 +1938,12 @@ async function isPortInUse(host, port) {
|
|
|
808
1938
|
}
|
|
809
1939
|
async function handleHqShortCircuit(flags) {
|
|
810
1940
|
if (flags["hq"] !== true) return null;
|
|
811
|
-
const { startHqServer } = await import("./hq-server-
|
|
1941
|
+
const { startHqServer } = await import("./hq-server-PBRU275L.js");
|
|
812
1942
|
const tunnelRequested = flags["tunnel"] === true;
|
|
813
1943
|
const host = typeof flags["host"] === "string" ? flags["host"] : tunnelRequested ? "127.0.0.1" : HQ_CLI_DEFAULT_HOST2;
|
|
814
1944
|
if (tunnelRequested && !isLoopbackHost(host)) {
|
|
815
1945
|
process.stderr.write(
|
|
816
|
-
`${
|
|
1946
|
+
`${color6.red("\u2717")} --tunnel requires a loopback origin. Remove --host or use --host 127.0.0.1.
|
|
817
1947
|
`
|
|
818
1948
|
);
|
|
819
1949
|
return 1;
|
|
@@ -824,7 +1954,7 @@ async function handleHqShortCircuit(flags) {
|
|
|
824
1954
|
if (Number.isFinite(parsed) && parsed > 0 && parsed < 65536) {
|
|
825
1955
|
port = parsed;
|
|
826
1956
|
} else {
|
|
827
|
-
process.stderr.write(`${
|
|
1957
|
+
process.stderr.write(`${color6.red("\u2717")} Invalid --port value: ${flags["port"]}
|
|
828
1958
|
`);
|
|
829
1959
|
return 1;
|
|
830
1960
|
}
|
|
@@ -832,7 +1962,7 @@ async function handleHqShortCircuit(flags) {
|
|
|
832
1962
|
const dataDir = typeof flags["data-dir"] === "string" ? flags["data-dir"] : void 0;
|
|
833
1963
|
const password = typeof flags["password"] === "string" ? flags["password"] : process.env.WRONGSTACK_HQ_PASSWORD;
|
|
834
1964
|
if (password !== void 0 && password.length < 8) {
|
|
835
|
-
process.stderr.write(`${
|
|
1965
|
+
process.stderr.write(`${color6.red("\u2717")} HQ password must be at least 8 characters.
|
|
836
1966
|
`);
|
|
837
1967
|
return 1;
|
|
838
1968
|
}
|
|
@@ -841,14 +1971,14 @@ async function handleHqShortCircuit(flags) {
|
|
|
841
1971
|
const existing = await isHqAlreadyRunning(resolvedDataDir);
|
|
842
1972
|
if (existing) {
|
|
843
1973
|
process.stderr.write(
|
|
844
|
-
`${
|
|
1974
|
+
`${color6.red("\u2717")} HQ is already running at ${existing.url} (PID ${existing.pid}). Stop it first or use a different --data-dir.
|
|
845
1975
|
`
|
|
846
1976
|
);
|
|
847
1977
|
return 1;
|
|
848
1978
|
}
|
|
849
1979
|
if (await isPortInUse(host, port)) {
|
|
850
1980
|
process.stderr.write(
|
|
851
|
-
`${
|
|
1981
|
+
`${color6.red("\u2717")} Port ${port} is already in use. Choose a different port or stop the process using it.
|
|
852
1982
|
`
|
|
853
1983
|
);
|
|
854
1984
|
return 1;
|
|
@@ -859,7 +1989,7 @@ async function handleHqShortCircuit(flags) {
|
|
|
859
1989
|
const { parseTokenTtlValue } = await import("./hq-ttl-U2FAYFAT.js");
|
|
860
1990
|
const parsed = parseTokenTtlValue(rawTtl);
|
|
861
1991
|
if (parsed.error) {
|
|
862
|
-
process.stderr.write(`${
|
|
1992
|
+
process.stderr.write(`${color6.red("\u2717")} Invalid --hq-token-ttl: ${parsed.error}
|
|
863
1993
|
`);
|
|
864
1994
|
return 1;
|
|
865
1995
|
}
|
|
@@ -883,11 +2013,11 @@ async function handleHqShortCircuit(flags) {
|
|
|
883
2013
|
const msg = err instanceof Error ? err.message : String(err);
|
|
884
2014
|
if (err instanceof Error && "code" in err && err.code === "EADDRINUSE") {
|
|
885
2015
|
process.stderr.write(
|
|
886
|
-
`${
|
|
2016
|
+
`${color6.red("\u2717")} Port ${port} is already in use. Please choose a different port.
|
|
887
2017
|
`
|
|
888
2018
|
);
|
|
889
2019
|
} else {
|
|
890
|
-
process.stderr.write(`${
|
|
2020
|
+
process.stderr.write(`${color6.red("\u2717")} Failed to start HQ server: ${msg}
|
|
891
2021
|
`);
|
|
892
2022
|
}
|
|
893
2023
|
return 1;
|
|
@@ -898,7 +2028,7 @@ async function handleHqShortCircuit(flags) {
|
|
|
898
2028
|
if (handle.firstRunSetup !== void 0 && !handle.firstRunSetup.browserTokenMode && !handle.firstRunSetup.passwordMode) {
|
|
899
2029
|
await handle.close();
|
|
900
2030
|
process.stderr.write(
|
|
901
|
-
`${
|
|
2031
|
+
`${color6.red("\u2717")} Refusing to publish HQ in open mode. Set --password or create a browser token first.
|
|
902
2032
|
`
|
|
903
2033
|
);
|
|
904
2034
|
return 1;
|
|
@@ -907,7 +2037,7 @@ async function handleHqShortCircuit(flags) {
|
|
|
907
2037
|
const { buildPublicHqUrl, startHqQuickTunnel } = await import("./hq-tunnel-RFKGC4HI.js");
|
|
908
2038
|
const originHost = handle.host === "::1" ? "[::1]" : handle.host;
|
|
909
2039
|
tunnel = await startHqQuickTunnel(`http://${originHost}:${handle.port}`, {
|
|
910
|
-
onUnexpectedExit: (message) => process.stderr.write(`${
|
|
2040
|
+
onUnexpectedExit: (message) => process.stderr.write(`${color6.yellow("!")} ${message}
|
|
911
2041
|
`)
|
|
912
2042
|
});
|
|
913
2043
|
handle.trustPublicOrigin(new URL(tunnel.url).origin);
|
|
@@ -917,16 +2047,16 @@ async function handleHqShortCircuit(flags) {
|
|
|
917
2047
|
handle.firstRunSetup?.passwordMode !== true
|
|
918
2048
|
);
|
|
919
2049
|
process.stdout.write(`
|
|
920
|
-
${
|
|
2050
|
+
${color6.green("Cloudflare Quick Tunnel ready:")} ${browserUrl}
|
|
921
2051
|
`);
|
|
922
2052
|
process.stdout.write(
|
|
923
|
-
`${
|
|
2053
|
+
`${color6.dim("Temporary development URL; DNS may need a few seconds, it changes on restart and ends when HQ stops.")}
|
|
924
2054
|
`
|
|
925
2055
|
);
|
|
926
2056
|
} catch (err) {
|
|
927
2057
|
await handle.close();
|
|
928
2058
|
process.stderr.write(
|
|
929
|
-
`${
|
|
2059
|
+
`${color6.red("\u2717")} Failed to start Cloudflare Quick Tunnel: ${err instanceof Error ? err.message : String(err)}
|
|
930
2060
|
`
|
|
931
2061
|
);
|
|
932
2062
|
return 1;
|
|
@@ -978,14 +2108,14 @@ import { TOKENS as TOKENS2 } from "@wrongstack/core/kernel";
|
|
|
978
2108
|
import { DefaultModelsRegistry } from "@wrongstack/core/models";
|
|
979
2109
|
import { ToolRegistry } from "@wrongstack/core/registry";
|
|
980
2110
|
import { normalizeTokenSavingTier } from "@wrongstack/core/types";
|
|
981
|
-
import { color as
|
|
2111
|
+
import { color as color13, isStdinTTY as isStdinTTY2, writeErr } from "@wrongstack/core/utils";
|
|
982
2112
|
import { createDefaultContainer as createDefaultContainer2 } from "@wrongstack/runtime";
|
|
983
2113
|
import { registerBuiltinToolTier } from "@wrongstack/tools/tool-tier";
|
|
984
2114
|
|
|
985
2115
|
// src/boot/config-backup-recovery.ts
|
|
986
2116
|
import * as fs2 from "node:fs/promises";
|
|
987
2117
|
import * as path4 from "node:path";
|
|
988
|
-
import { atomicWrite as atomicWrite2, backupConfigFile, color as
|
|
2118
|
+
import { atomicWrite as atomicWrite2, backupConfigFile, color as color7, toErrorMessage } from "@wrongstack/core/utils";
|
|
989
2119
|
function isRecord(value) {
|
|
990
2120
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
991
2121
|
}
|
|
@@ -1069,12 +2199,12 @@ async function maybeRestoreDefaultProfileFromBackup(opts) {
|
|
|
1069
2199
|
const providerSummary = remainder > 0 ? `${shownProviders} +${remainder}` : shownProviders;
|
|
1070
2200
|
opts.renderer.write(
|
|
1071
2201
|
`
|
|
1072
|
-
${
|
|
1073
|
-
${
|
|
2202
|
+
${color7.amber("\u25CB")} ${color7.bold("default")} profile has no saved providers.
|
|
2203
|
+
${color7.dim("Latest usable backup:")} ${color7.bold(backup.fileName)} ${color7.dim(`(${backup.providerIds.length} provider: ${providerSummary})`)}
|
|
1074
2204
|
`
|
|
1075
2205
|
);
|
|
1076
2206
|
const answer = (await opts.reader.readLine(
|
|
1077
|
-
` ${
|
|
2207
|
+
` ${color7.amber("?")} Restore all settings from this backup? ${color7.dim("[Y/n]")} `
|
|
1078
2208
|
)).trim().toLowerCase();
|
|
1079
2209
|
if (answer === "n" || answer === "no") return false;
|
|
1080
2210
|
try {
|
|
@@ -1084,7 +2214,7 @@ async function maybeRestoreDefaultProfileFromBackup(opts) {
|
|
|
1084
2214
|
profilePath: opts.profilePath
|
|
1085
2215
|
});
|
|
1086
2216
|
opts.renderer.write(
|
|
1087
|
-
` ${
|
|
2217
|
+
` ${color7.green("\u2713")} Restored all settings from ${color7.dim(backup.fileName)}
|
|
1088
2218
|
`
|
|
1089
2219
|
);
|
|
1090
2220
|
return true;
|
|
@@ -1101,11 +2231,11 @@ import {
|
|
|
1101
2231
|
buildIdentityLayer,
|
|
1102
2232
|
loadInstructionBundle
|
|
1103
2233
|
} from "@wrongstack/core/agent";
|
|
1104
|
-
import { atomicWrite as atomicWrite4, color as
|
|
2234
|
+
import { atomicWrite as atomicWrite4, color as color10, estimateTextTokens } from "@wrongstack/core/utils";
|
|
1105
2235
|
|
|
1106
2236
|
// src/pre-launch/launch-prompts.ts
|
|
1107
2237
|
import * as fs3 from "node:fs/promises";
|
|
1108
|
-
import { atomicWrite as atomicWrite3, color as
|
|
2238
|
+
import { atomicWrite as atomicWrite3, color as color8 } from "@wrongstack/core/utils";
|
|
1109
2239
|
var LaunchAbortedError = class extends Error {
|
|
1110
2240
|
exitCode = 0;
|
|
1111
2241
|
constructor() {
|
|
@@ -1136,19 +2266,19 @@ async function runLaunchPrompts(opts) {
|
|
|
1136
2266
|
yolo: yoloPinned ?? lastChoices.yolo,
|
|
1137
2267
|
autonomy: autonomyPinned ?? lastChoices.autonomy
|
|
1138
2268
|
};
|
|
1139
|
-
const onOff = (v) => v ?
|
|
2269
|
+
const onOff = (v) => v ? color8.green("on") : color8.dim("off");
|
|
1140
2270
|
const modeLabel = effective.mode.toUpperCase();
|
|
1141
2271
|
renderer.write(
|
|
1142
2272
|
`
|
|
1143
|
-
${
|
|
2273
|
+
${color8.dim("Last settings:")} ${color8.bold(modeLabel)} \xB7 YOLO ${onOff(effective.yolo)} \xB7 Autonomy ${effective.autonomy === "auto" ? color8.green("auto") : color8.dim("off")}
|
|
1144
2274
|
`
|
|
1145
2275
|
);
|
|
1146
2276
|
const answer = (await reader.readLine(
|
|
1147
|
-
` ${
|
|
2277
|
+
` ${color8.amber("?")} Continue with these? ${color8.dim("[Y/n/q]")} ${color8.dim("(auto Y in 5s)")} `,
|
|
1148
2278
|
{ timeoutMs: 5e3, defaultAnswer: "y" }
|
|
1149
2279
|
)).trim().toLowerCase();
|
|
1150
2280
|
if (answer === "q") {
|
|
1151
|
-
renderer.write(
|
|
2281
|
+
renderer.write(color8.dim(" Goodbye!\n"));
|
|
1152
2282
|
throw new LaunchAbortedError();
|
|
1153
2283
|
}
|
|
1154
2284
|
if (answer !== "n" && answer !== "no") {
|
|
@@ -1156,7 +2286,7 @@ async function runLaunchPrompts(opts) {
|
|
|
1156
2286
|
const badgeStr2 = badges2.length > 0 ? ` (${badges2.join(" \xB7 ")})` : "";
|
|
1157
2287
|
renderer.write(
|
|
1158
2288
|
`
|
|
1159
|
-
${
|
|
2289
|
+
${color8.green("\u25B6")} Launching in ${color8.bold(modeLabel)} mode${badgeStr2}
|
|
1160
2290
|
|
|
1161
2291
|
`
|
|
1162
2292
|
);
|
|
@@ -1169,10 +2299,10 @@ async function runLaunchPrompts(opts) {
|
|
|
1169
2299
|
} else {
|
|
1170
2300
|
const answer = (await reader.readLine(
|
|
1171
2301
|
`
|
|
1172
|
-
${
|
|
2302
|
+
${color8.amber("?")} Interactive mode: ${color8.bold("T")}UI / ${color8.bold("R")}EPL ${color8.dim("[T/r/q]")} `
|
|
1173
2303
|
)).trim().toLowerCase();
|
|
1174
2304
|
if (answer === "q") {
|
|
1175
|
-
renderer.write(
|
|
2305
|
+
renderer.write(color8.dim(" Goodbye!\n"));
|
|
1176
2306
|
throw new LaunchAbortedError();
|
|
1177
2307
|
}
|
|
1178
2308
|
mode = answer === "r" || answer === "repl" ? "repl" : "tui";
|
|
@@ -1182,10 +2312,10 @@ async function runLaunchPrompts(opts) {
|
|
|
1182
2312
|
yolo = yoloPinned;
|
|
1183
2313
|
} else {
|
|
1184
2314
|
const answer = (await reader.readLine(
|
|
1185
|
-
` ${
|
|
2315
|
+
` ${color8.amber("?")} YOLO mode ${color8.dim("(auto-approve tool calls)")} ${color8.dim("[Y/n/q]")} `
|
|
1186
2316
|
)).trim().toLowerCase();
|
|
1187
2317
|
if (answer === "q") {
|
|
1188
|
-
renderer.write(
|
|
2318
|
+
renderer.write(color8.dim(" Goodbye!\n"));
|
|
1189
2319
|
throw new LaunchAbortedError();
|
|
1190
2320
|
}
|
|
1191
2321
|
yolo = answer !== "n" && answer !== "no";
|
|
@@ -1195,10 +2325,10 @@ async function runLaunchPrompts(opts) {
|
|
|
1195
2325
|
autonomy = autonomyPinned;
|
|
1196
2326
|
} else {
|
|
1197
2327
|
const answer = (await reader.readLine(
|
|
1198
|
-
` ${
|
|
2328
|
+
` ${color8.amber("?")} Autonomy mode ${color8.dim("(auto-continue \u2014 agent picks next step)")} ${color8.dim("[Y/n/q]")} `
|
|
1199
2329
|
)).trim().toLowerCase();
|
|
1200
2330
|
if (answer === "q") {
|
|
1201
|
-
renderer.write(
|
|
2331
|
+
renderer.write(color8.dim(" Goodbye!\n"));
|
|
1202
2332
|
throw new LaunchAbortedError();
|
|
1203
2333
|
}
|
|
1204
2334
|
autonomy = answer !== "n" && answer !== "no" ? "auto" : "off";
|
|
@@ -1207,7 +2337,7 @@ async function runLaunchPrompts(opts) {
|
|
|
1207
2337
|
const badgeStr = badges.length > 0 ? ` (${badges.join(" \xB7 ")})` : "";
|
|
1208
2338
|
renderer.write(
|
|
1209
2339
|
`
|
|
1210
|
-
${
|
|
2340
|
+
${color8.green("\u25B6")} Launching in ${color8.bold(mode.toUpperCase())} mode${badgeStr}
|
|
1211
2341
|
|
|
1212
2342
|
`
|
|
1213
2343
|
);
|
|
@@ -1215,9 +2345,9 @@ async function runLaunchPrompts(opts) {
|
|
|
1215
2345
|
}
|
|
1216
2346
|
function buildBadges(chosen) {
|
|
1217
2347
|
const badges = [];
|
|
1218
|
-
if (chosen.yolo) badges.push(
|
|
2348
|
+
if (chosen.yolo) badges.push(color8.yellow("YOLO"));
|
|
1219
2349
|
if (chosen.autonomy !== "off")
|
|
1220
|
-
badges.push(
|
|
2350
|
+
badges.push(color8.magenta(`AUTONOMY:${chosen.autonomy.toUpperCase()}`));
|
|
1221
2351
|
return badges;
|
|
1222
2352
|
}
|
|
1223
2353
|
async function persistLaunchChoices(configPath, choices) {
|
|
@@ -1251,7 +2381,7 @@ async function persistLaunchChoices(configPath, choices) {
|
|
|
1251
2381
|
// src/pre-launch/project-check.ts
|
|
1252
2382
|
import * as fs4 from "node:fs/promises";
|
|
1253
2383
|
import * as path5 from "node:path";
|
|
1254
|
-
import { color as
|
|
2384
|
+
import { color as color9, toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
|
|
1255
2385
|
var MANIFESTS = [
|
|
1256
2386
|
"package.json",
|
|
1257
2387
|
"pyproject.toml",
|
|
@@ -1294,7 +2424,7 @@ async function runProjectCheck(opts) {
|
|
|
1294
2424
|
if (kind === "initialized") {
|
|
1295
2425
|
renderer.write(
|
|
1296
2426
|
`
|
|
1297
|
-
${
|
|
2427
|
+
${color9.green("\u2713")} Project initialized ${color9.dim(`(${path5.join(projectRoot, ".wrongstack", "AGENTS.md")})`)}
|
|
1298
2428
|
`
|
|
1299
2429
|
);
|
|
1300
2430
|
return true;
|
|
@@ -1302,20 +2432,20 @@ async function runProjectCheck(opts) {
|
|
|
1302
2432
|
if (kind === "project") {
|
|
1303
2433
|
renderer.write(
|
|
1304
2434
|
`
|
|
1305
|
-
${
|
|
2435
|
+
${color9.amber("\u25CF")} Project detected ${color9.dim(`(${projectRoot})`)} but ${color9.bold(".wrongstack/AGENTS.md")} is missing.
|
|
1306
2436
|
`
|
|
1307
2437
|
);
|
|
1308
2438
|
const answer2 = (await reader.readLine(
|
|
1309
|
-
` ${
|
|
2439
|
+
` ${color9.amber("?")} Scaffold ${color9.bold("AGENTS.md")} now? ${color9.dim("[y/N/q]")} `
|
|
1310
2440
|
)).trim().toLowerCase();
|
|
1311
2441
|
if (answer2 === "q") {
|
|
1312
|
-
renderer.write(
|
|
2442
|
+
renderer.write(color9.dim(" Cancelled.\n"));
|
|
1313
2443
|
return false;
|
|
1314
2444
|
}
|
|
1315
2445
|
if (answer2 === "y" || answer2 === "yes") {
|
|
1316
2446
|
try {
|
|
1317
2447
|
const file = await scaffoldAgentsMd(projectRoot);
|
|
1318
|
-
renderer.write(` ${
|
|
2448
|
+
renderer.write(` ${color9.green("\u2713")} Wrote ${color9.dim(file)}
|
|
1319
2449
|
`);
|
|
1320
2450
|
} catch (err) {
|
|
1321
2451
|
renderer.writeError(`Failed to scaffold AGENTS.md: ${toErrorMessage2(err)}`);
|
|
@@ -1333,14 +2463,14 @@ async function runProjectCheck(opts) {
|
|
|
1333
2463
|
if (!hasGit) {
|
|
1334
2464
|
renderer.write(
|
|
1335
2465
|
`
|
|
1336
|
-
${
|
|
2466
|
+
${color9.dim("\u25CB")} ${color9.dim(`No project manifest in ${projectRoot} \u2014 running in a scratch directory.`)}
|
|
1337
2467
|
`
|
|
1338
2468
|
);
|
|
1339
2469
|
const answer2 = (await reader.readLine(
|
|
1340
|
-
` ${
|
|
2470
|
+
` ${color9.amber("?")} No git repo found. ${color9.bold("Initialize git?")} ${color9.dim("[y/N/q]")} `
|
|
1341
2471
|
)).trim().toLowerCase();
|
|
1342
2472
|
if (answer2 === "q") {
|
|
1343
|
-
renderer.write(
|
|
2473
|
+
renderer.write(color9.dim(" Cancelled.\n"));
|
|
1344
2474
|
return false;
|
|
1345
2475
|
}
|
|
1346
2476
|
if (answer2 === "y" || answer2 === "yes") {
|
|
@@ -1358,7 +2488,7 @@ async function runProjectCheck(opts) {
|
|
|
1358
2488
|
(code) => code === 0 ? resolve2() : reject(new Error(`git init failed with ${code}`))
|
|
1359
2489
|
);
|
|
1360
2490
|
});
|
|
1361
|
-
renderer.write(` ${
|
|
2491
|
+
renderer.write(` ${color9.green("\u2713")} Git repository initialized
|
|
1362
2492
|
`);
|
|
1363
2493
|
} catch (err) {
|
|
1364
2494
|
renderer.writeError(`git init failed: ${toErrorMessage2(err)}
|
|
@@ -1368,13 +2498,13 @@ async function runProjectCheck(opts) {
|
|
|
1368
2498
|
} else {
|
|
1369
2499
|
renderer.write(
|
|
1370
2500
|
`
|
|
1371
|
-
${
|
|
2501
|
+
${color9.dim("\u25CB")} ${color9.dim(`No project manifest in ${projectRoot} \u2014 running in a scratch directory.`)}
|
|
1372
2502
|
`
|
|
1373
2503
|
);
|
|
1374
2504
|
}
|
|
1375
|
-
const answer = (await reader.readLine(` ${
|
|
2505
|
+
const answer = (await reader.readLine(` ${color9.amber("?")} Continue anyway? ${color9.dim("[Y/n/q]")} `)).trim().toLowerCase();
|
|
1376
2506
|
if (answer === "q" || answer === "n" || answer === "no") {
|
|
1377
|
-
renderer.write(
|
|
2507
|
+
renderer.write(color9.dim(" Cancelled.\n"));
|
|
1378
2508
|
return false;
|
|
1379
2509
|
}
|
|
1380
2510
|
return true;
|
|
@@ -1447,28 +2577,28 @@ async function runSystemPromptMenu(deps) {
|
|
|
1447
2577
|
const defaultVariant = lastVariant ?? "default";
|
|
1448
2578
|
if (lastVariant) {
|
|
1449
2579
|
const answer2 = (await reader.readLine(
|
|
1450
|
-
` ${
|
|
2580
|
+
` ${color10.amber("?")} Continue with ${color10.bold(labelFor(lastVariant))} system prompt ${color10.dim(`(~${fmtTok(tokens[lastVariant])} tokens)`)}? ${color10.dim("[Y/n/q]")} ${color10.dim("(auto Y in 5s)")} `,
|
|
1451
2581
|
{ timeoutMs: SUMMARY_TIMEOUT_MS2, defaultAnswer: "y" }
|
|
1452
2582
|
)).trim().toLowerCase();
|
|
1453
2583
|
if (answer2 === "q" || answer2 === "quit") throw new LaunchAbortedError();
|
|
1454
2584
|
if (answer2 !== "n" && answer2 !== "no") return lastVariant;
|
|
1455
2585
|
}
|
|
1456
2586
|
renderer.write(`
|
|
1457
|
-
${
|
|
2587
|
+
${color10.amber("?")} System prompt:
|
|
1458
2588
|
`);
|
|
1459
2589
|
for (const [index, opt] of SYSTEM_PROMPT_OPTIONS.entries()) {
|
|
1460
2590
|
const num2 = index + 1;
|
|
1461
2591
|
const isDefault = opt.variant === defaultVariant;
|
|
1462
|
-
const marker = isDefault ?
|
|
1463
|
-
const label = isDefault ?
|
|
2592
|
+
const marker = isDefault ? color10.cyan("\u25CF") : color10.dim("\u25CB");
|
|
2593
|
+
const label = isDefault ? color10.bold(opt.label) : opt.label;
|
|
1464
2594
|
renderer.write(
|
|
1465
|
-
` ${
|
|
2595
|
+
` ${color10.dim(`${num2}.`)} ${marker} ${label.padEnd(9)} ${color10.dim(`~${fmtTok(tokens[opt.variant])} tokens`)} ${color10.dim(opt.hint)}
|
|
1466
2596
|
`
|
|
1467
2597
|
);
|
|
1468
2598
|
}
|
|
1469
2599
|
const answer = (await reader.readLine(
|
|
1470
2600
|
`
|
|
1471
|
-
${
|
|
2601
|
+
${color10.amber("?")} Select system prompt ${color10.dim(`[1-${SYSTEM_PROMPT_OPTIONS.length}, Enter = ${labelFor(defaultVariant)}, q to quit]`)}: `
|
|
1472
2602
|
)).trim().toLowerCase();
|
|
1473
2603
|
if (answer === "q" || answer === "quit") throw new LaunchAbortedError();
|
|
1474
2604
|
if (!answer) return defaultVariant;
|
|
@@ -1828,7 +2958,7 @@ function dim(s) {
|
|
|
1828
2958
|
// src/launch-hints.ts
|
|
1829
2959
|
import * as fs7 from "node:fs/promises";
|
|
1830
2960
|
import * as path7 from "node:path";
|
|
1831
|
-
import { color as
|
|
2961
|
+
import { color as color11 } from "@wrongstack/core/utils";
|
|
1832
2962
|
var GROUPS = [
|
|
1833
2963
|
{
|
|
1834
2964
|
title: "Autonomy",
|
|
@@ -1988,7 +3118,7 @@ function wrapWords(value, firstWidth, continuationWidth = firstWidth) {
|
|
|
1988
3118
|
function renderHintLines(item, termWidth) {
|
|
1989
3119
|
const inline = `${HINT_INDENT}${item.key} \u2014 ${item.blurb}`;
|
|
1990
3120
|
if (displayWidth(inline) <= termWidth) {
|
|
1991
|
-
return [`${HINT_INDENT}${
|
|
3121
|
+
return [`${HINT_INDENT}${color11.bold(item.key)} ${color11.dim("\u2014")} ${color11.dim(item.blurb)}`];
|
|
1992
3122
|
}
|
|
1993
3123
|
const lines = [];
|
|
1994
3124
|
const keyLines = wrapWords(
|
|
@@ -1998,13 +3128,13 @@ function renderHintLines(item, termWidth) {
|
|
|
1998
3128
|
);
|
|
1999
3129
|
keyLines.forEach((line, index) => {
|
|
2000
3130
|
const indent = index === 0 ? HINT_INDENT : HINT_CONTINUATION_INDENT;
|
|
2001
|
-
lines.push(`${indent}${
|
|
3131
|
+
lines.push(`${indent}${color11.bold(line)}`);
|
|
2002
3132
|
});
|
|
2003
3133
|
const blurbLines = wrapWords(
|
|
2004
3134
|
`\u2014 ${item.blurb}`,
|
|
2005
3135
|
termWidth - displayWidth(HINT_CONTINUATION_INDENT)
|
|
2006
3136
|
);
|
|
2007
|
-
for (const line of blurbLines) lines.push(`${HINT_CONTINUATION_INDENT}${
|
|
3137
|
+
for (const line of blurbLines) lines.push(`${HINT_CONTINUATION_INDENT}${color11.dim(line)}`);
|
|
2008
3138
|
return lines;
|
|
2009
3139
|
}
|
|
2010
3140
|
function renderHeaderLines(group, groupIndex, termWidth) {
|
|
@@ -2012,24 +3142,24 @@ function renderHeaderLines(group, groupIndex, termWidth) {
|
|
|
2012
3142
|
const plain = ` ${group.title} ${progress}`;
|
|
2013
3143
|
if (displayWidth(plain) <= termWidth) {
|
|
2014
3144
|
return [
|
|
2015
|
-
` ${
|
|
2016
|
-
` ${
|
|
3145
|
+
` ${color11.cyan("\u25C7")} ${color11.bold(group.title)} ${color11.dim(progress)}`,
|
|
3146
|
+
` ${color11.dim("\u2500".repeat(Math.min(termWidth - 2, 48)))}`
|
|
2017
3147
|
];
|
|
2018
3148
|
}
|
|
2019
3149
|
return [
|
|
2020
|
-
` ${
|
|
2021
|
-
` ${
|
|
3150
|
+
` ${color11.cyan("\u25C7")} ${color11.bold(group.title)}`,
|
|
3151
|
+
` ${color11.dim("\u2500".repeat(Math.min(termWidth - 2, 48)))}`
|
|
2022
3152
|
];
|
|
2023
3153
|
}
|
|
2024
3154
|
function renderFooterLines(termWidth) {
|
|
2025
3155
|
const footer = "/help lists everything \xB7 hide with --no-hints";
|
|
2026
3156
|
if (displayWidth(` ${footer}`) <= termWidth) {
|
|
2027
3157
|
return [
|
|
2028
|
-
` ${
|
|
2029
|
-
` ${
|
|
3158
|
+
` ${color11.dim("\u2500".repeat(Math.min(termWidth - 2, 48)))}`,
|
|
3159
|
+
` ${color11.dim(`${color11.bold("/help")} lists everything \xB7 hide with ${color11.bold("--no-hints")}`)}`
|
|
2030
3160
|
];
|
|
2031
3161
|
}
|
|
2032
|
-
return [...wrapWords(footer, termWidth - 2).map((line) => ` ${
|
|
3162
|
+
return [...wrapWords(footer, termWidth - 2).map((line) => ` ${color11.dim(line)}`)];
|
|
2033
3163
|
}
|
|
2034
3164
|
async function pickGroupIndex(opts) {
|
|
2035
3165
|
if (typeof opts.groupIndex === "number") return wrap(opts.groupIndex);
|
|
@@ -2071,7 +3201,7 @@ async function printLaunchHints(renderer, flags, opts = {}) {
|
|
|
2071
3201
|
}
|
|
2072
3202
|
|
|
2073
3203
|
// src/renderer.ts
|
|
2074
|
-
import { color as
|
|
3204
|
+
import { color as color12 } from "@wrongstack/core/utils";
|
|
2075
3205
|
var TerminalRenderer = class _TerminalRenderer {
|
|
2076
3206
|
out;
|
|
2077
3207
|
err;
|
|
@@ -2184,7 +3314,7 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2184
3314
|
if (!this.lineStart) this.out.write("\n");
|
|
2185
3315
|
const arrow = theme.primary("\u2192");
|
|
2186
3316
|
const display = formatInputSummary(input);
|
|
2187
|
-
this.out.write(`${arrow} ${theme.bold(name)}${display ?
|
|
3317
|
+
this.out.write(`${arrow} ${theme.bold(name)}${display ? color12.dim(` ${display}`) : ""}
|
|
2188
3318
|
`);
|
|
2189
3319
|
this.lineStart = true;
|
|
2190
3320
|
}
|
|
@@ -2201,7 +3331,7 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2201
3331
|
if (isError) {
|
|
2202
3332
|
const firstLine = txt.split("\n")[0] ?? "";
|
|
2203
3333
|
const truncated = firstLine.length > 200 ? `${firstLine.slice(0, 197)}\u2026` : firstLine;
|
|
2204
|
-
this.out.write(` ${prefix} ${
|
|
3334
|
+
this.out.write(` ${prefix} ${color12.dim(truncated)}
|
|
2205
3335
|
`);
|
|
2206
3336
|
this.lineStart = true;
|
|
2207
3337
|
return;
|
|
@@ -2209,7 +3339,7 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2209
3339
|
const isEditLike = name === "edit" || name === "write";
|
|
2210
3340
|
const diff = extractDiff(content);
|
|
2211
3341
|
if (isEditLike && diff) {
|
|
2212
|
-
this.out.write(` ${prefix} ${
|
|
3342
|
+
this.out.write(` ${prefix} ${color12.dim(summarize(content, name))}
|
|
2213
3343
|
`);
|
|
2214
3344
|
const rendered = renderDiff(diff).split("\n").map((l) => ` ${l}`).join("\n");
|
|
2215
3345
|
this.out.write(`${rendered}
|
|
@@ -2220,7 +3350,7 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2220
3350
|
const summary = summarize(content, name);
|
|
2221
3351
|
const isReadLike = name === "read" || name === "grep" || name === "glob" || name === "bash" || name === "exec";
|
|
2222
3352
|
if (renderMode === "simple") {
|
|
2223
|
-
this.out.write(` ${prefix} ${
|
|
3353
|
+
this.out.write(` ${prefix} ${color12.dim(summary || compactSingleLine(bodyText))}
|
|
2224
3354
|
`);
|
|
2225
3355
|
this.lineStart = true;
|
|
2226
3356
|
return;
|
|
@@ -2229,16 +3359,16 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2229
3359
|
const lines = bodyText.split("\n");
|
|
2230
3360
|
const head = lines.slice(0, previewLines).map((l) => l.replace(/\s+$/, ""));
|
|
2231
3361
|
const moreCount = Math.max(0, lines.length - head.length);
|
|
2232
|
-
this.out.write(` ${prefix} ${
|
|
3362
|
+
this.out.write(` ${prefix} ${color12.dim(summary)}
|
|
2233
3363
|
`);
|
|
2234
3364
|
for (const l of head) {
|
|
2235
3365
|
const capped = l.length > 200 ? `${l.slice(0, 197)}\u2026` : l;
|
|
2236
|
-
this.out.write(` ${
|
|
3366
|
+
this.out.write(` ${color12.dim(capped)}
|
|
2237
3367
|
`);
|
|
2238
3368
|
}
|
|
2239
3369
|
if (moreCount > 0) {
|
|
2240
3370
|
this.out.write(
|
|
2241
|
-
` ${
|
|
3371
|
+
` ${color12.dim(`+${moreCount} more line${moreCount === 1 ? "" : "s"}`)}
|
|
2242
3372
|
`
|
|
2243
3373
|
);
|
|
2244
3374
|
}
|
|
@@ -2358,7 +3488,7 @@ function renderMarkdown(s) {
|
|
|
2358
3488
|
return theme.primary(theme.bold(`${hashes} ${text}`));
|
|
2359
3489
|
});
|
|
2360
3490
|
out = out.replace(/```([a-zA-Z0-9_+-]*)\n([\s\S]*?)```/g, (_m, _lang, code) => {
|
|
2361
|
-
return
|
|
3491
|
+
return color12.gray(`
|
|
2362
3492
|
\u250C\u2500
|
|
2363
3493
|
${code.replace(/^/gm, "\u2502 ")}\u2514\u2500`);
|
|
2364
3494
|
});
|
|
@@ -2366,7 +3496,7 @@ ${code.replace(/^/gm, "\u2502 ")}\u2514\u2500`);
|
|
|
2366
3496
|
out = out.replace(/\*\*([^*]+)\*\*/g, (_m, text) => theme.bold(text));
|
|
2367
3497
|
out = out.replace(
|
|
2368
3498
|
/(^|[^*])\*([^*\n]+)\*([^*]|$)/g,
|
|
2369
|
-
(_m, l, t, r) => `${l}${
|
|
3499
|
+
(_m, l, t, r) => `${l}${color12.italic(t)}${r}`
|
|
2370
3500
|
);
|
|
2371
3501
|
return out;
|
|
2372
3502
|
}
|
|
@@ -2708,6 +3838,17 @@ async function boot(argv) {
|
|
|
2708
3838
|
});
|
|
2709
3839
|
const subcommandHandler = first ? subcommands[first] : void 0;
|
|
2710
3840
|
if (first && subcommandHandler) {
|
|
3841
|
+
if (flags["help"] === true || flags["h"] === true) {
|
|
3842
|
+
const deepSub = positional[1];
|
|
3843
|
+
if (deepSub && renderDeepHelp(`${first}:${deepSub}`, renderer)) {
|
|
3844
|
+
await reader.close();
|
|
3845
|
+
return 0;
|
|
3846
|
+
}
|
|
3847
|
+
if (renderFocusedHelp(first, renderer)) {
|
|
3848
|
+
await reader.close();
|
|
3849
|
+
return 0;
|
|
3850
|
+
}
|
|
3851
|
+
}
|
|
2711
3852
|
const container = createDefaultContainer2({
|
|
2712
3853
|
config,
|
|
2713
3854
|
wpaths,
|
|
@@ -2744,8 +3885,8 @@ async function boot(argv) {
|
|
|
2744
3885
|
if (isHomeDirectory(cwd, userHome)) {
|
|
2745
3886
|
writeErr(
|
|
2746
3887
|
`
|
|
2747
|
-
${
|
|
2748
|
-
${
|
|
3888
|
+
${color13.red(color13.bold("\u26A0 This is not a working directory."))}
|
|
3889
|
+
${color13.red("Please open wstack in a project folder.")}
|
|
2749
3890
|
|
|
2750
3891
|
`
|
|
2751
3892
|
);
|
|
@@ -2793,8 +3934,12 @@ async function boot(argv) {
|
|
|
2793
3934
|
const modelFlag = typeof flags["model"] === "string" ? flags["model"] : void 0;
|
|
2794
3935
|
const noInteractiveMode = flags["webui"] || flags["no-interactive"];
|
|
2795
3936
|
if (noInteractiveMode && (!config.provider || !config.model)) {
|
|
2796
|
-
|
|
2797
|
-
|
|
3937
|
+
if (providerFlag && modelFlag) {
|
|
3938
|
+
config = patchConfig(config, { provider: providerFlag, model: modelFlag });
|
|
3939
|
+
} else {
|
|
3940
|
+
const picked = await autoSelectSavedProvider(config, modelsRegistry);
|
|
3941
|
+
if (picked) config = patchConfig(config, picked);
|
|
3942
|
+
}
|
|
2798
3943
|
}
|
|
2799
3944
|
if (!(!!providerFlag && !!modelFlag)) {
|
|
2800
3945
|
if (isStdinTTY2() && !noInteractiveMode) {
|
|
@@ -2806,7 +3951,7 @@ async function boot(argv) {
|
|
|
2806
3951
|
const savedStatus = await validateSavedProviderModel(config, modelsRegistry);
|
|
2807
3952
|
renderer.write(
|
|
2808
3953
|
`
|
|
2809
|
-
${
|
|
3954
|
+
${color13.dim("Last settings:")} ${color13.bold(savedProvider)} / ${color13.bold(savedModel)}
|
|
2810
3955
|
`
|
|
2811
3956
|
);
|
|
2812
3957
|
if (!savedStatus.ok) {
|
|
@@ -2816,11 +3961,11 @@ async function boot(argv) {
|
|
|
2816
3961
|
);
|
|
2817
3962
|
} else {
|
|
2818
3963
|
const answer = (await reader.readLine(
|
|
2819
|
-
` ${
|
|
3964
|
+
` ${color13.amber("?")} Continue with these? ${color13.dim("[Y/n/q]")} ${color13.dim("(auto Y in 5s)")} `,
|
|
2820
3965
|
{ timeoutMs: 5e3, defaultAnswer: "y" }
|
|
2821
3966
|
)).trim().toLowerCase();
|
|
2822
3967
|
if (answer === "q") {
|
|
2823
|
-
renderer.write(
|
|
3968
|
+
renderer.write(color13.dim(" Goodbye!\n"));
|
|
2824
3969
|
await reader.close();
|
|
2825
3970
|
return 0;
|
|
2826
3971
|
}
|
|
@@ -2828,7 +3973,7 @@ async function boot(argv) {
|
|
|
2828
3973
|
skipPicker = true;
|
|
2829
3974
|
renderer.write(
|
|
2830
3975
|
`
|
|
2831
|
-
${
|
|
3976
|
+
${color13.green("\u25B6")} ${color13.bold(savedProvider)} / ${color13.bold(savedModel)}
|
|
2832
3977
|
|
|
2833
3978
|
`
|
|
2834
3979
|
);
|
|
@@ -2963,8 +4108,8 @@ async function boot(argv) {
|
|
|
2963
4108
|
if (shouldPrintYoloNotice(lastChoices, yoloPinned, choices.yolo)) {
|
|
2964
4109
|
writeErr(
|
|
2965
4110
|
`
|
|
2966
|
-
${
|
|
2967
|
-
${
|
|
4111
|
+
${color13.yellow("YOLO is on")}: non-denied tool calls, including shell and file writes, run without confirmation.
|
|
4112
|
+
${color13.dim("Explicit deny rules still apply. Use")} --no-yolo ${color13.dim("or")} /yolo off ${color13.dim("to require prompts.")}
|
|
2968
4113
|
|
|
2969
4114
|
`
|
|
2970
4115
|
);
|
|
@@ -3030,10 +4175,10 @@ async function checkGitInCwd(opts) {
|
|
|
3030
4175
|
if (!hasCwdGit) {
|
|
3031
4176
|
renderer.write(
|
|
3032
4177
|
`
|
|
3033
|
-
${
|
|
4178
|
+
${color13.amber("\u25CB")} This folder has no ${color13.bold(".git")} repository.
|
|
3034
4179
|
`
|
|
3035
4180
|
);
|
|
3036
|
-
const answer = (await reader.readLine(` ${
|
|
4181
|
+
const answer = (await reader.readLine(` ${color13.amber("?")} Initialize one here? ${color13.dim("[y/N]")} `)).trim().toLowerCase();
|
|
3037
4182
|
if (answer === "y" || answer === "yes") {
|
|
3038
4183
|
try {
|
|
3039
4184
|
const { spawn: spawn2 } = await import("node:child_process");
|
|
@@ -3049,7 +4194,7 @@ async function checkGitInCwd(opts) {
|
|
|
3049
4194
|
(code) => code === 0 ? resolve2() : reject(new Error(`git init failed with ${code}`))
|
|
3050
4195
|
);
|
|
3051
4196
|
});
|
|
3052
|
-
renderer.write(` ${
|
|
4197
|
+
renderer.write(` ${color13.green("\u2713")} Git repository initialized
|
|
3053
4198
|
`);
|
|
3054
4199
|
hasCwdGit = true;
|
|
3055
4200
|
} catch (err) {
|
|
@@ -3063,7 +4208,7 @@ async function checkGitInCwd(opts) {
|
|
|
3063
4208
|
try {
|
|
3064
4209
|
await fs8.access(path8.join(parentDir, ".git"));
|
|
3065
4210
|
renderer.write(
|
|
3066
|
-
` ${
|
|
4211
|
+
` ${color13.dim("\u2139")} A ${color13.bold(".git")} repo exists in the parent directory: ${color13.dim(parentDir)}
|
|
3067
4212
|
`
|
|
3068
4213
|
);
|
|
3069
4214
|
} catch {
|
|
@@ -3302,7 +4447,7 @@ async function initializeCli(argv) {
|
|
|
3302
4447
|
async function main(argv) {
|
|
3303
4448
|
const cliCtx = await initializeCli(argv);
|
|
3304
4449
|
if (typeof cliCtx === "number") return cliCtx;
|
|
3305
|
-
const { runInteractive } = await import("./cli-main-
|
|
4450
|
+
const { runInteractive } = await import("./cli-main-YDOZZOZA.js");
|
|
3306
4451
|
return runInteractive(cliCtx);
|
|
3307
4452
|
}
|
|
3308
4453
|
|