@wrongstack/cli 1.0.24 → 1.0.26
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/data/providers.json +44 -0
- package/dist/{acp-AJWSKWE5.js → acp-LI665LO2.js} +5 -5
- package/dist/ascii-mode-SG4PRNLP.js +7 -0
- package/dist/{auth-GRBZ7Y3D.js → auth-TE55JF4Z.js} +14 -14
- package/dist/{bench-N5K7Z5O3.js → bench-GTLPM22B.js} +2 -2
- package/dist/boot/append-system-prompt.d.ts +10 -0
- package/dist/boot/ascii-mode.d.ts +12 -0
- package/dist/boot/container-wiring.d.ts +4 -2
- package/dist/boot/dispatch-singleshot.d.ts +4 -1
- package/dist/boot/mcp-config-flag.d.ts +22 -0
- package/dist/boot/piped-stdin.d.ts +40 -0
- package/dist/boot/restricted-mode.d.ts +15 -0
- package/dist/boot/safe-mode.d.ts +30 -0
- package/dist/boot/single-shot-budget.d.ts +30 -0
- package/dist/boot/stream-json.d.ts +36 -0
- package/dist/boot/structured-output.d.ts +16 -0
- package/dist/boot/system-prompt-builder.d.ts +2 -0
- package/dist/boot/tool-restriction-flags.d.ts +36 -0
- package/dist/boot/worktree-sessions.d.ts +21 -0
- package/dist/boot-provider-selection.d.ts +67 -0
- package/dist/boot.d.ts +1 -38
- package/dist/{chunk-LFMVHT3R.js → chunk-2ERX3RPN.js} +11 -13
- package/dist/chunk-4TVYGG6G.js +62 -0
- package/dist/chunk-5JYDKG5B.js +154 -0
- package/dist/{chunk-3VXYY5JC.js → chunk-5UZBUV2H.js} +3 -19
- package/dist/chunk-BEHGRNOQ.js +58 -0
- package/dist/chunk-CZTXF6HY.js +140 -0
- package/dist/{chunk-SKPDE62W.js → chunk-EPR42SWM.js} +36 -6
- package/dist/{chunk-YBUCXXYZ.js → chunk-F5DCFAKI.js} +1 -1
- package/dist/chunk-HLSHFXTO.js +97 -0
- package/dist/{chunk-BLD5DSVA.js → chunk-KJS5543T.js} +2 -2
- package/dist/{chunk-QFPQXKCG.js → chunk-KOEO4CJG.js} +21 -6
- package/dist/chunk-LBPLTTZ6.js +105 -0
- package/dist/{chunk-3OCUS3VN.js → chunk-LDCGZJTC.js} +4 -4
- package/dist/chunk-LKPEBZBE.js +143 -0
- package/dist/{chunk-DRM7PSW7.js → chunk-OAVBM55Q.js} +3 -3
- package/dist/chunk-PZQBGUVZ.js +18 -0
- package/dist/{chunk-MHEBWVXL.js → chunk-Q4INH2DG.js} +46 -2
- package/dist/{chunk-ZZRSG7VK.js → chunk-RZ4ZDRYA.js} +3 -3
- package/dist/{chunk-U46QR4WR.js → chunk-TI7KLHYX.js} +132 -3
- package/dist/{chunk-PGKJ2OQP.js → chunk-WQV2NP57.js} +5 -5
- package/dist/chunk-X756ZS72.js +329 -0
- package/dist/{chunk-JF2MULWF.js → chunk-YHYINL47.js} +47 -15
- package/dist/{cli-context-34Q5IJRA.js → cli-context-UVGAN3NO.js} +407 -327
- package/dist/{cli-main-AELJDBGU.js → cli-main-TN3KZ2P6.js} +2652 -1978
- package/dist/cli-update-notice.d.ts +2 -1
- package/dist/config-doctor.d.ts +1 -1
- package/dist/{diag-doctor-WIFJH3XH.js → diag-doctor-BIZAFIAT.js} +2 -2
- package/dist/{execution-PYC5FCS4.js → execution-7QIP6GRY.js} +1948 -1666
- package/dist/fleet/host-types.d.ts +3 -1
- package/dist/goal-commands.d.ts +47 -0
- package/dist/goal-host.d.ts +1 -14
- package/dist/{hq-JTUTFI4L.js → hq-GLZ7QESM.js} +6 -6
- package/dist/{hq-server-PC7GZMPT.js → hq-server-YTKDVQPY.js} +2 -2
- package/dist/{hq-service-NW56MUP2.js → hq-service-BMMJAHRT.js} +4 -4
- package/dist/import-claude-code-32PCSIQI.js +236 -0
- package/dist/index.js +12 -8
- package/dist/{mailbox-serve-WDOCH6KR.js → mailbox-serve-NW5VZG7R.js} +3 -3
- package/dist/{modeldiag-36OGAL5C.js → modeldiag-36VODVIH.js} +8 -8
- package/dist/{per-subcommand-help-XE77MTGJ.js → per-subcommand-help-QDAQASPZ.js} +2 -2
- package/dist/permission-prompt.d.ts +14 -0
- package/dist/permission-rules-view.d.ts +18 -0
- package/dist/{permissions-CFDLXETM.js → permissions-PL27UHYD.js} +67 -45
- package/dist/{plugin-usage-S5LVGMBW.js → plugin-usage-CIGOOTX3.js} +2 -2
- package/dist/{plugins-RHBIVLI7.js → plugins-HQTXUD6A.js} +4 -2
- package/dist/preflight.d.ts +1 -1
- package/dist/{projects-LMNAGGEU.js → projects-T4CZCA25.js} +3 -6
- package/dist/provider-helpers.d.ts +7 -11
- package/dist/{providers-models-2CFG46RD.js → providers-models-5Z2PJTEW.js} +5 -5
- package/dist/release-asset-download.d.ts +10 -0
- package/dist/release-attestation.d.ts +28 -0
- package/dist/remote/remote-session.d.ts +64 -0
- package/dist/remote/remote-target.d.ts +69 -0
- package/dist/remote-O5WXHLWV.js +561 -0
- package/dist/{replay-Z3FTJEMM.js → replay-DEI566CW.js} +2 -2
- package/dist/services/commit-message.d.ts +2 -1
- package/dist/session-move-P2EC2COA.js +44 -0
- package/dist/session-move.d.ts +20 -0
- package/dist/session-stats.d.ts +10 -0
- package/dist/{sessions-config-IQUH2GXT.js → sessions-config-SXTTLNXA.js} +35 -5
- package/dist/short-circuit-flags-74Y5N6CF.js +10 -0
- package/dist/slash-commands/command-context.d.ts +15 -5
- package/dist/slash-commands/goal-refiner.d.ts +4 -49
- package/dist/slash-commands/mcp.d.ts +2 -1
- package/dist/slash-commands/permissions.d.ts +4 -0
- package/dist/slash-commands/settings-context-mutations.d.ts +5 -0
- package/dist/slash-commands/settings-limits-mutations.d.ts +12 -0
- package/dist/standalone-auto-update-TOTRGCSA.js +249 -0
- package/dist/standalone-auto-update.d.ts +65 -0
- package/dist/standalone-update-LZO3MNLH.js +24 -0
- package/dist/standalone-update.d.ts +37 -1
- package/dist/subcommands/handlers/import-claude-code.d.ts +42 -0
- package/dist/subcommands/handlers/permissions.d.ts +9 -3
- package/dist/subcommands/handlers/remote.d.ts +6 -0
- package/dist/subcommands/handlers/version-help.d.ts +5 -0
- package/dist/{subcommands-ZTSIN7LG.js → subcommands-Q6ORSB2E.js} +2 -2
- package/dist/tui-resume-callback.d.ts +18 -0
- package/dist/{typesafe-HVEVPA6R.js → typesafe-U7YB2RRV.js} +5 -5
- package/dist/{typesafe-topic-replay-4W73BOLV.js → typesafe-topic-replay-ZILIU3WS.js} +18 -2
- package/dist/{update-7XIOEXTD.js → update-TDZX4IL2.js} +4 -4
- package/dist/{update-check-2POMBHFB.js → update-check-J5ZVKS73.js} +3 -3
- package/dist/version-JB2UAV2A.js +11 -0
- package/dist/version-help-XJJQ7YSH.js +10 -0
- package/dist/webui-server/route-contexts.d.ts +1 -1
- package/dist/webui-server/session-start-payload.d.ts +5 -1
- package/dist/{webui-server-L2SICPTB.js → webui-server-YTHLRFD2.js} +509 -366
- package/dist/webui-server-lifecycle.d.ts +57 -0
- package/dist/webui-server.d.ts +0 -14
- package/dist/wiring/brain-and-orchestration.d.ts +3 -1
- package/dist/wiring/cli-prompt-and-tools-setup.d.ts +9 -0
- package/dist/wiring/cli-slash-commands-setup.d.ts +1 -0
- package/dist/wiring/lifecycle-plugins.d.ts +4 -2
- package/dist/wiring/metrics.d.ts +9 -1
- package/dist/wiring/pipeline.d.ts +2 -7
- package/dist/wiring/plugins.d.ts +3 -0
- package/dist/wiring/provider-status.d.ts +1 -0
- package/dist/wiring/provider-utility-tools.d.ts +3 -1
- package/package.json +28 -28
- package/dist/chunk-2BKFWIER.js +0 -98
- package/dist/chunk-424ORSE7.js +0 -56
- package/dist/chunk-QBBF7GIK.js +0 -65
- package/dist/short-circuit-flags-SDT53OML.js +0 -10
- package/dist/standalone-update-MW47J3AK.js +0 -164
- package/dist/version-help-WZ623NWM.js +0 -10
|
@@ -1,35 +1,43 @@
|
|
|
1
1
|
import {
|
|
2
|
+
activateRestrictedMode,
|
|
3
|
+
announceSafeMode,
|
|
2
4
|
applySimpleUiFullAutoProfile,
|
|
3
5
|
detectProjectFacts,
|
|
4
6
|
isSimpleUiFullAuto,
|
|
5
|
-
|
|
7
|
+
makeStdinPromptDelegate,
|
|
6
8
|
renderAgentsTemplate,
|
|
7
|
-
renderDiff
|
|
8
|
-
|
|
9
|
+
renderDiff,
|
|
10
|
+
resolveLaunchAllowedTools,
|
|
11
|
+
resolveToolRestriction
|
|
12
|
+
} from "./chunk-TI7KLHYX.js";
|
|
13
|
+
import {
|
|
14
|
+
parseOutputFormat,
|
|
15
|
+
resolveJsonSchemaFlag
|
|
16
|
+
} from "./chunk-LKPEBZBE.js";
|
|
9
17
|
import {
|
|
10
18
|
theme as theme2
|
|
11
19
|
} from "./chunk-QD544J2B.js";
|
|
12
|
-
import {
|
|
13
|
-
fmtTok,
|
|
14
|
-
patchConfig
|
|
15
|
-
} from "./chunk-EWKESL4L.js";
|
|
16
20
|
import {
|
|
17
21
|
parseWebuiSessionChildOptions,
|
|
18
22
|
writeWebuiSessionChildError
|
|
19
23
|
} from "./chunk-ZMX5HRLI.js";
|
|
24
|
+
import {
|
|
25
|
+
fmtTok,
|
|
26
|
+
patchConfig
|
|
27
|
+
} from "./chunk-EWKESL4L.js";
|
|
20
28
|
import {
|
|
21
29
|
subcommands
|
|
22
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-BEHGRNOQ.js";
|
|
23
31
|
import {
|
|
24
32
|
renderDeepHelp,
|
|
25
33
|
renderFocusedHelp
|
|
26
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-EPR42SWM.js";
|
|
27
35
|
import {
|
|
28
36
|
handleHelpVersionShortCircuit
|
|
29
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-WQV2NP57.js";
|
|
30
38
|
import {
|
|
31
39
|
DEFAULT_PORT
|
|
32
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-OAVBM55Q.js";
|
|
33
41
|
import "./chunk-HXJYHAR4.js";
|
|
34
42
|
import {
|
|
35
43
|
resolveHqPasswordInput
|
|
@@ -38,20 +46,34 @@ import {
|
|
|
38
46
|
normalizeHqPublicOrigin
|
|
39
47
|
} from "./chunk-5EA6OTLJ.js";
|
|
40
48
|
import {
|
|
41
|
-
|
|
42
|
-
} from "./chunk-
|
|
49
|
+
resolveLaunchMcpServers
|
|
50
|
+
} from "./chunk-HLSHFXTO.js";
|
|
43
51
|
import {
|
|
44
52
|
installProviderPersisters
|
|
45
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-LDCGZJTC.js";
|
|
54
|
+
import {
|
|
55
|
+
parseHqIpAllowlist
|
|
56
|
+
} from "./chunk-Q7E3BPDU.js";
|
|
46
57
|
import {
|
|
47
58
|
discoverAndMergeProviders
|
|
48
59
|
} from "./chunk-D5GB5MHA.js";
|
|
60
|
+
import {
|
|
61
|
+
runUpdateCommand
|
|
62
|
+
} from "./chunk-KOEO4CJG.js";
|
|
63
|
+
import "./chunk-U3SS4NRH.js";
|
|
49
64
|
import {
|
|
50
65
|
applyNodeEnvDefault,
|
|
51
66
|
applySessionShellDefault,
|
|
52
67
|
runPreflight
|
|
53
|
-
} from "./chunk-
|
|
54
|
-
import "./chunk-
|
|
68
|
+
} from "./chunk-LBPLTTZ6.js";
|
|
69
|
+
import "./chunk-RZ4ZDRYA.js";
|
|
70
|
+
import {
|
|
71
|
+
applyAsciiMode
|
|
72
|
+
} from "./chunk-PZQBGUVZ.js";
|
|
73
|
+
import "./chunk-5JYDKG5B.js";
|
|
74
|
+
import {
|
|
75
|
+
CLI_VERSION
|
|
76
|
+
} from "./chunk-F5DCFAKI.js";
|
|
55
77
|
import {
|
|
56
78
|
addFromCatalog,
|
|
57
79
|
boxBottom,
|
|
@@ -63,31 +85,23 @@ import {
|
|
|
63
85
|
runPicker,
|
|
64
86
|
saveToGlobalConfig,
|
|
65
87
|
theme
|
|
66
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-2ERX3RPN.js";
|
|
67
89
|
import "./chunk-YTEOAWOJ.js";
|
|
68
90
|
import {
|
|
69
91
|
isKeylessLocalProvider,
|
|
70
92
|
visibleModelIds
|
|
71
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-5UZBUV2H.js";
|
|
94
|
+
import {
|
|
95
|
+
resolveActiveApiKey
|
|
96
|
+
} from "./chunk-LUMETJFO.js";
|
|
97
|
+
import "./chunk-DAKVBMD4.js";
|
|
72
98
|
import {
|
|
73
99
|
activeProfileConfigPath
|
|
74
100
|
} from "./chunk-YMXXOOFN.js";
|
|
75
101
|
import "./chunk-WSTVGC2C.js";
|
|
76
102
|
import {
|
|
77
103
|
parseArgs
|
|
78
|
-
} from "./chunk-
|
|
79
|
-
import "./chunk-DAKVBMD4.js";
|
|
80
|
-
import {
|
|
81
|
-
resolveActiveApiKey
|
|
82
|
-
} from "./chunk-LUMETJFO.js";
|
|
83
|
-
import {
|
|
84
|
-
runUpdateCommand
|
|
85
|
-
} from "./chunk-QFPQXKCG.js";
|
|
86
|
-
import "./chunk-U3SS4NRH.js";
|
|
87
|
-
import "./chunk-ZZRSG7VK.js";
|
|
88
|
-
import {
|
|
89
|
-
CLI_VERSION
|
|
90
|
-
} from "./chunk-YBUCXXYZ.js";
|
|
104
|
+
} from "./chunk-Q4INH2DG.js";
|
|
91
105
|
|
|
92
106
|
// src/cli-context.ts
|
|
93
107
|
import { TOKENS as TOKENS3 } from "@wrongstack/core/kernel";
|
|
@@ -192,12 +206,13 @@ function wireContainer(deps) {
|
|
|
192
206
|
events,
|
|
193
207
|
permission: {
|
|
194
208
|
yolo: deps.config.yolo,
|
|
209
|
+
launchAllowedTools: deps.launchAllowedTools,
|
|
195
210
|
// Wrapped so the REPL's terminal prompt also appears on the HQ
|
|
196
211
|
// dashboard and can be answered from there. The wrapper is a no-op
|
|
197
212
|
// until `approvalMirror.current` is populated (HQ telemetry boot), and
|
|
198
213
|
// the terminal prompt itself behaves exactly as it always has.
|
|
199
214
|
promptDelegate: makeMirroredPromptDelegate({
|
|
200
|
-
inner:
|
|
215
|
+
inner: makeStdinPromptDelegate(deps.reader),
|
|
201
216
|
getRegistry: () => approvalMirror.current,
|
|
202
217
|
getSessionId: () => approvalMirror.sessionId?.()
|
|
203
218
|
})
|
|
@@ -475,7 +490,7 @@ async function promptModeArrow(deps) {
|
|
|
475
490
|
const { renderer } = deps;
|
|
476
491
|
const stdin = process.stdin;
|
|
477
492
|
const out = (s) => renderer.write(s);
|
|
478
|
-
return await new Promise((
|
|
493
|
+
return await new Promise((resolve3) => {
|
|
479
494
|
let index = 0;
|
|
480
495
|
let drawn = 0;
|
|
481
496
|
let remaining = Math.round(MENU_TIMEOUT_MS / 1e3);
|
|
@@ -530,7 +545,7 @@ async function promptModeArrow(deps) {
|
|
|
530
545
|
out("\x1B[0J");
|
|
531
546
|
out(finalLine);
|
|
532
547
|
out("\x1B[?25h");
|
|
533
|
-
|
|
548
|
+
resolve3(result);
|
|
534
549
|
};
|
|
535
550
|
const pick = () => {
|
|
536
551
|
const opt = MODE_OPTIONS[index];
|
|
@@ -589,7 +604,7 @@ async function promptModeArrow(deps) {
|
|
|
589
604
|
setRawMode(stdin, true);
|
|
590
605
|
stdin.resume();
|
|
591
606
|
} catch {
|
|
592
|
-
|
|
607
|
+
resolve3(null);
|
|
593
608
|
return;
|
|
594
609
|
}
|
|
595
610
|
out("\x1B[?25l");
|
|
@@ -854,7 +869,7 @@ async function launchDesktop(args) {
|
|
|
854
869
|
);
|
|
855
870
|
return 1;
|
|
856
871
|
}
|
|
857
|
-
return await new Promise((
|
|
872
|
+
return await new Promise((resolve3) => {
|
|
858
873
|
const env = { ...process.env };
|
|
859
874
|
if (native) delete env["ELECTRON_RUN_AS_NODE"];
|
|
860
875
|
const child = spawn(executable, launchArgs, {
|
|
@@ -867,11 +882,11 @@ async function launchDesktop(args) {
|
|
|
867
882
|
`${color2.red("\u2717 Failed to start WrongStack Desktop:")} ${err.message}
|
|
868
883
|
`
|
|
869
884
|
);
|
|
870
|
-
|
|
885
|
+
resolve3(1);
|
|
871
886
|
});
|
|
872
887
|
child.once("exit", (code, signal) => {
|
|
873
|
-
if (typeof code === "number")
|
|
874
|
-
else
|
|
888
|
+
if (typeof code === "number") resolve3(code);
|
|
889
|
+
else resolve3(signal ? 1 : 0);
|
|
875
890
|
});
|
|
876
891
|
});
|
|
877
892
|
}
|
|
@@ -896,24 +911,24 @@ async function isHqAlreadyRunning(dataDir) {
|
|
|
896
911
|
return null;
|
|
897
912
|
}
|
|
898
913
|
async function isPortInUse(host, port) {
|
|
899
|
-
return new Promise((
|
|
914
|
+
return new Promise((resolve3) => {
|
|
900
915
|
const server = net.createServer();
|
|
901
916
|
server.once("error", (err) => {
|
|
902
917
|
if (err.code === "EADDRINUSE") {
|
|
903
|
-
|
|
918
|
+
resolve3(true);
|
|
904
919
|
} else {
|
|
905
|
-
|
|
920
|
+
resolve3(false);
|
|
906
921
|
}
|
|
907
922
|
});
|
|
908
923
|
server.once("listening", () => {
|
|
909
|
-
server.close(() =>
|
|
924
|
+
server.close(() => resolve3(false));
|
|
910
925
|
});
|
|
911
926
|
server.listen(port, host);
|
|
912
927
|
});
|
|
913
928
|
}
|
|
914
929
|
async function handleHqShortCircuit(flags) {
|
|
915
930
|
if (flags["hq"] !== true) return null;
|
|
916
|
-
const { startHqServer } = await import("./hq-server-
|
|
931
|
+
const { startHqServer } = await import("./hq-server-YTKDVQPY.js");
|
|
917
932
|
const tunnelRequested = flags["tunnel"] === true;
|
|
918
933
|
const rawPublicUrl = typeof flags["hq-public-url"] === "string" ? flags["hq-public-url"] : process.env.WRONGSTACK_HQ_PUBLIC_URL;
|
|
919
934
|
let publicOrigin;
|
|
@@ -1127,7 +1142,7 @@ ${color3.green("Cloudflare Quick Tunnel ready:")} ${browserUrl}
|
|
|
1127
1142
|
} catch {
|
|
1128
1143
|
}
|
|
1129
1144
|
}
|
|
1130
|
-
await new Promise((
|
|
1145
|
+
await new Promise((resolve3) => {
|
|
1131
1146
|
const shutdown = async () => {
|
|
1132
1147
|
const results = await Promise.allSettled([
|
|
1133
1148
|
...tunnel ? [tunnel.close()] : [],
|
|
@@ -1146,7 +1161,7 @@ ${color3.green("Cloudflare Quick Tunnel ready:")} ${browserUrl}
|
|
|
1146
1161
|
})
|
|
1147
1162
|
);
|
|
1148
1163
|
}
|
|
1149
|
-
|
|
1164
|
+
resolve3();
|
|
1150
1165
|
};
|
|
1151
1166
|
process.on("SIGINT", shutdown);
|
|
1152
1167
|
process.on("SIGTERM", shutdown);
|
|
@@ -1155,26 +1170,195 @@ ${color3.green("Cloudflare Quick Tunnel ready:")} ${browserUrl}
|
|
|
1155
1170
|
}
|
|
1156
1171
|
|
|
1157
1172
|
// src/boot.ts
|
|
1158
|
-
import * as fs6 from "node:fs/promises";
|
|
1159
|
-
import { createRequire as createRequire4 } from "node:module";
|
|
1160
1173
|
import * as os from "node:os";
|
|
1161
|
-
import * as
|
|
1174
|
+
import * as path9 from "node:path";
|
|
1175
|
+
import { toErrorMessage as toErrorMessage5 } from "@wrongstack/core/utils";
|
|
1176
|
+
|
|
1177
|
+
// src/boot-provider-selection.ts
|
|
1178
|
+
import * as fs2 from "node:fs/promises";
|
|
1179
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
1180
|
+
import * as path4 from "node:path";
|
|
1162
1181
|
import { fileURLToPath } from "node:url";
|
|
1163
|
-
import {
|
|
1182
|
+
import {
|
|
1183
|
+
color as color4,
|
|
1184
|
+
moduleUrlFor,
|
|
1185
|
+
toErrorMessage,
|
|
1186
|
+
wrongstackPackageJsonPath as wrongstackPackageJsonPath3
|
|
1187
|
+
} from "@wrongstack/core/utils";
|
|
1188
|
+
import { isSetupProvider } from "@wrongstack/providers";
|
|
1189
|
+
function resolveBundledOverlayFile() {
|
|
1190
|
+
try {
|
|
1191
|
+
return fileURLToPath(
|
|
1192
|
+
new URL("../data/providers.json", moduleUrlFor(import.meta.url, "@wrongstack/cli"))
|
|
1193
|
+
);
|
|
1194
|
+
} catch {
|
|
1195
|
+
return void 0;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
async function validateSavedProviderModel(config, modelsRegistry) {
|
|
1199
|
+
const providerId = config.provider;
|
|
1200
|
+
const modelId = config.model;
|
|
1201
|
+
if (!providerId || !modelId) return { ok: false, reason: "missing provider/model" };
|
|
1202
|
+
if (isSetupProvider(providerId)) return { ok: true };
|
|
1203
|
+
const saved = config.providers?.[providerId];
|
|
1204
|
+
const lookupId = saved?.type && saved.type !== providerId ? saved.type : providerId;
|
|
1205
|
+
const catalogProvider = await modelsRegistry.getProvider(lookupId).catch(() => void 0);
|
|
1206
|
+
if (!catalogProvider && !saved?.family)
|
|
1207
|
+
return { ok: false, reason: `provider "${providerId}" is no longer available` };
|
|
1208
|
+
const hasCredential = (catalogProvider?.envVars ?? saved?.envVars ?? []).some(
|
|
1209
|
+
(envVar) => Boolean(process.env[envVar])
|
|
1210
|
+
) || saved !== void 0 && resolveActiveApiKey(saved) !== void 0 || isKeylessLocalProvider({
|
|
1211
|
+
apiBase: saved?.baseUrl ?? catalogProvider?.apiBase,
|
|
1212
|
+
envVars: saved?.envVars ?? catalogProvider?.envVars
|
|
1213
|
+
});
|
|
1214
|
+
if (!hasCredential) return { ok: false, reason: `provider "${providerId}" has no usable key` };
|
|
1215
|
+
const visible = visibleModelIds(
|
|
1216
|
+
providerId,
|
|
1217
|
+
config,
|
|
1218
|
+
(catalogProvider?.models ?? []).map((m) => m.id),
|
|
1219
|
+
saved
|
|
1220
|
+
);
|
|
1221
|
+
if (visible.length > 0 && !visible.includes(modelId)) {
|
|
1222
|
+
return {
|
|
1223
|
+
ok: false,
|
|
1224
|
+
reason: `model "${modelId}" is no longer available for provider "${providerId}"`
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
return { ok: true };
|
|
1228
|
+
}
|
|
1229
|
+
async function autoSelectSavedProvider(config, modelsRegistry) {
|
|
1230
|
+
const providers = config.providers ?? {};
|
|
1231
|
+
const entries = config.provider && providers[config.provider] ? [[config.provider, providers[config.provider]]] : Object.entries(providers);
|
|
1232
|
+
for (const [id, cfg] of entries) {
|
|
1233
|
+
if (!cfg) continue;
|
|
1234
|
+
let model = cfg.models?.[0];
|
|
1235
|
+
if (!model) {
|
|
1236
|
+
const catalogId = cfg.type && cfg.type !== id ? cfg.type : id;
|
|
1237
|
+
const catalog = await modelsRegistry.getProvider(catalogId).catch(() => void 0);
|
|
1238
|
+
model = catalog?.models?.[0]?.id;
|
|
1239
|
+
}
|
|
1240
|
+
if (model) return { provider: id, model };
|
|
1241
|
+
}
|
|
1242
|
+
return void 0;
|
|
1243
|
+
}
|
|
1244
|
+
function resolveBundledSkillsDir2() {
|
|
1245
|
+
try {
|
|
1246
|
+
const req = createRequire4(import.meta.url);
|
|
1247
|
+
const corePkg = wrongstackPackageJsonPath3("@wrongstack/core", (id) => req.resolve(id));
|
|
1248
|
+
return path4.join(path4.dirname(corePkg), "skills");
|
|
1249
|
+
} catch {
|
|
1250
|
+
return void 0;
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
function resolveBundledPromptsDir2() {
|
|
1254
|
+
try {
|
|
1255
|
+
const req = createRequire4(import.meta.url);
|
|
1256
|
+
const corePkg = wrongstackPackageJsonPath3("@wrongstack/core", (id) => req.resolve(id));
|
|
1257
|
+
return path4.join(path4.dirname(corePkg), "data", "prompts");
|
|
1258
|
+
} catch {
|
|
1259
|
+
return void 0;
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
function isHomeDirectory(cwd, userHome) {
|
|
1263
|
+
if (!cwd || !userHome) return false;
|
|
1264
|
+
return path4.resolve(cwd) === path4.resolve(userHome);
|
|
1265
|
+
}
|
|
1266
|
+
function shouldPrintYoloNotice(lastChoices, yoloPinned, yolo) {
|
|
1267
|
+
return !lastChoices && yoloPinned === void 0 && yolo;
|
|
1268
|
+
}
|
|
1269
|
+
async function checkGitInCwd(opts) {
|
|
1270
|
+
const { cwd, renderer, reader } = opts;
|
|
1271
|
+
const cwdGit = path4.join(cwd, ".git");
|
|
1272
|
+
let hasCwdGit = false;
|
|
1273
|
+
try {
|
|
1274
|
+
await fs2.access(cwdGit);
|
|
1275
|
+
hasCwdGit = true;
|
|
1276
|
+
} catch {
|
|
1277
|
+
}
|
|
1278
|
+
if (!hasCwdGit) {
|
|
1279
|
+
renderer.write(
|
|
1280
|
+
`
|
|
1281
|
+
${color4.amber("\u25CB")} This folder has no ${color4.bold(".git")} repository.
|
|
1282
|
+
`
|
|
1283
|
+
);
|
|
1284
|
+
const answer = (await reader.readLine(` ${color4.amber("?")} Initialize one here? ${color4.dim("[y/N]")} `)).trim().toLowerCase();
|
|
1285
|
+
if (answer === "y" || answer === "yes") {
|
|
1286
|
+
try {
|
|
1287
|
+
const { spawn: spawn2 } = await import("node:child_process");
|
|
1288
|
+
await new Promise((resolve3, reject) => {
|
|
1289
|
+
const child = spawn2("git", ["init"], {
|
|
1290
|
+
cwd,
|
|
1291
|
+
signal: AbortSignal.timeout(1e4),
|
|
1292
|
+
windowsHide: true
|
|
1293
|
+
});
|
|
1294
|
+
child.on("error", reject);
|
|
1295
|
+
child.on(
|
|
1296
|
+
"close",
|
|
1297
|
+
(code) => code === 0 ? resolve3() : reject(new Error(`git init failed with ${code}`))
|
|
1298
|
+
);
|
|
1299
|
+
});
|
|
1300
|
+
renderer.write(` ${color4.green("\u2713")} Git repository initialized
|
|
1301
|
+
`);
|
|
1302
|
+
hasCwdGit = true;
|
|
1303
|
+
} catch (err) {
|
|
1304
|
+
renderer.writeError(`git init failed: ${toErrorMessage(err)}
|
|
1305
|
+
`);
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
const parentDir = path4.dirname(cwd);
|
|
1310
|
+
if (parentDir !== cwd) {
|
|
1311
|
+
try {
|
|
1312
|
+
await fs2.access(path4.join(parentDir, ".git"));
|
|
1313
|
+
renderer.write(
|
|
1314
|
+
` ${color4.dim("\u2139")} A ${color4.bold(".git")} repo exists in the parent directory: ${color4.dim(parentDir)}
|
|
1315
|
+
`
|
|
1316
|
+
);
|
|
1317
|
+
} catch {
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
// src/boot.ts
|
|
1164
1323
|
import { DefaultLogger } from "@wrongstack/core/infrastructure";
|
|
1165
1324
|
import { TOKENS as TOKENS2 } from "@wrongstack/core/kernel";
|
|
1166
|
-
import { DefaultModelsRegistry } from "@wrongstack/core/models";
|
|
1325
|
+
import { DefaultModelsRegistry, startCatalog } from "@wrongstack/core/models";
|
|
1167
1326
|
import { ToolRegistry } from "@wrongstack/core/registry";
|
|
1168
1327
|
import { normalizeTokenSavingTier } from "@wrongstack/core/types";
|
|
1169
|
-
import { color as
|
|
1170
|
-
import { isSetupProvider, SETUP_MODEL_ID, SETUP_PROVIDER_ID } from "@wrongstack/providers";
|
|
1328
|
+
import { color as color11, isStdinTTY as isStdinTTY2, writeErr } from "@wrongstack/core/utils";
|
|
1329
|
+
import { isSetupProvider as isSetupProvider2, SETUP_MODEL_ID, SETUP_PROVIDER_ID } from "@wrongstack/providers";
|
|
1171
1330
|
import { createDefaultContainer as createDefaultContainer2 } from "@wrongstack/runtime";
|
|
1172
1331
|
import { registerBuiltinToolTier } from "@wrongstack/tools/tool-tier";
|
|
1173
1332
|
|
|
1333
|
+
// src/boot/append-system-prompt.ts
|
|
1334
|
+
import * as fs3 from "node:fs/promises";
|
|
1335
|
+
import * as path5 from "node:path";
|
|
1336
|
+
async function resolveAppendedSystemPrompt(flags, cwd) {
|
|
1337
|
+
const parts = [];
|
|
1338
|
+
const inline = flags["append-system-prompt"];
|
|
1339
|
+
if (typeof inline === "string" && inline.trim()) parts.push(inline.trim());
|
|
1340
|
+
const file = flags["append-system-prompt-file"];
|
|
1341
|
+
if (file === true) {
|
|
1342
|
+
throw new Error("--append-system-prompt-file needs a path");
|
|
1343
|
+
}
|
|
1344
|
+
if (typeof file === "string" && file.trim()) {
|
|
1345
|
+
const resolved = path5.resolve(cwd, file.trim());
|
|
1346
|
+
let text;
|
|
1347
|
+
try {
|
|
1348
|
+
text = await fs3.readFile(resolved, "utf8");
|
|
1349
|
+
} catch (err) {
|
|
1350
|
+
const reason = err.code ?? String(err);
|
|
1351
|
+
throw new Error(`--append-system-prompt-file: cannot read ${resolved} (${reason})`);
|
|
1352
|
+
}
|
|
1353
|
+
if (text.trim()) parts.push(text.trim());
|
|
1354
|
+
}
|
|
1355
|
+
return parts.length > 0 ? parts.join("\n\n") : void 0;
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1174
1358
|
// src/boot/config-backup-recovery.ts
|
|
1175
|
-
import * as
|
|
1176
|
-
import * as
|
|
1177
|
-
import { atomicWrite as atomicWrite2, backupConfigFile, color as
|
|
1359
|
+
import * as fs4 from "node:fs/promises";
|
|
1360
|
+
import * as path6 from "node:path";
|
|
1361
|
+
import { atomicWrite as atomicWrite2, backupConfigFile, color as color5, toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
|
|
1178
1362
|
function isRecord(value) {
|
|
1179
1363
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1180
1364
|
}
|
|
@@ -1185,7 +1369,7 @@ function providerIds(value) {
|
|
|
1185
1369
|
}
|
|
1186
1370
|
async function defaultProfileProvidersAreEmpty(profilePath) {
|
|
1187
1371
|
try {
|
|
1188
|
-
const parsed = JSON.parse(await
|
|
1372
|
+
const parsed = JSON.parse(await fs4.readFile(profilePath, "utf8"));
|
|
1189
1373
|
return providerIds(parsed).length === 0;
|
|
1190
1374
|
} catch {
|
|
1191
1375
|
return false;
|
|
@@ -1208,7 +1392,7 @@ function profileSnapshotTimestamp(fileName, fallback) {
|
|
|
1208
1392
|
);
|
|
1209
1393
|
}
|
|
1210
1394
|
async function findLatestProviderBackup(globalRoot, profileName = "default") {
|
|
1211
|
-
const directory =
|
|
1395
|
+
const directory = path6.join(globalRoot, "config-history");
|
|
1212
1396
|
const escapedProfile = profileName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1213
1397
|
const filePattern = new RegExp(
|
|
1214
1398
|
`^profiles-${escapedProfile}-config-\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}-\\d{3}\\.json$`,
|
|
@@ -1217,7 +1401,7 @@ async function findLatestProviderBackup(globalRoot, profileName = "default") {
|
|
|
1217
1401
|
const candidates = [];
|
|
1218
1402
|
let entries;
|
|
1219
1403
|
try {
|
|
1220
|
-
entries = await
|
|
1404
|
+
entries = await fs4.readdir(directory, { withFileTypes: true });
|
|
1221
1405
|
} catch {
|
|
1222
1406
|
return void 0;
|
|
1223
1407
|
}
|
|
@@ -1225,9 +1409,9 @@ async function findLatestProviderBackup(globalRoot, profileName = "default") {
|
|
|
1225
1409
|
if (!entry.isFile() || !filePattern.test(entry.name)) {
|
|
1226
1410
|
continue;
|
|
1227
1411
|
}
|
|
1228
|
-
const filePath =
|
|
1412
|
+
const filePath = path6.join(directory, entry.name);
|
|
1229
1413
|
try {
|
|
1230
|
-
const stat2 = await
|
|
1414
|
+
const stat2 = await fs4.stat(filePath);
|
|
1231
1415
|
candidates.push({
|
|
1232
1416
|
filePath,
|
|
1233
1417
|
fileName: entry.name,
|
|
@@ -1239,7 +1423,7 @@ async function findLatestProviderBackup(globalRoot, profileName = "default") {
|
|
|
1239
1423
|
candidates.sort((a, b) => b.modifiedAtMs - a.modifiedAtMs);
|
|
1240
1424
|
for (const candidate of candidates) {
|
|
1241
1425
|
try {
|
|
1242
|
-
const raw = await
|
|
1426
|
+
const raw = await fs4.readFile(candidate.filePath, "utf8");
|
|
1243
1427
|
const parsed = JSON.parse(raw);
|
|
1244
1428
|
const ids = providerIds(parsed);
|
|
1245
1429
|
if (ids.length === 0) continue;
|
|
@@ -1251,7 +1435,7 @@ async function findLatestProviderBackup(globalRoot, profileName = "default") {
|
|
|
1251
1435
|
}
|
|
1252
1436
|
async function restoreDefaultProfileBackup(opts) {
|
|
1253
1437
|
await backupConfigFile(opts.profilePath, { globalRoot: opts.globalRoot });
|
|
1254
|
-
await
|
|
1438
|
+
await fs4.mkdir(path6.dirname(opts.profilePath), { recursive: true });
|
|
1255
1439
|
await atomicWrite2(opts.profilePath, opts.backup.raw, { mode: 384 });
|
|
1256
1440
|
}
|
|
1257
1441
|
async function maybeRestoreDefaultProfileFromBackup(opts) {
|
|
@@ -1264,12 +1448,12 @@ async function maybeRestoreDefaultProfileFromBackup(opts) {
|
|
|
1264
1448
|
const providerSummary = remainder > 0 ? `${shownProviders} +${remainder}` : shownProviders;
|
|
1265
1449
|
opts.renderer.write(
|
|
1266
1450
|
`
|
|
1267
|
-
${
|
|
1268
|
-
${
|
|
1451
|
+
${color5.amber("\u25CB")} ${color5.bold(profileName)} profile has no saved providers.
|
|
1452
|
+
${color5.dim("Latest usable backup:")} ${color5.bold(backup.fileName)} ${color5.dim(`(${backup.providerIds.length} provider: ${providerSummary})`)}
|
|
1269
1453
|
`
|
|
1270
1454
|
);
|
|
1271
1455
|
const answer = (await opts.reader.readLine(
|
|
1272
|
-
` ${
|
|
1456
|
+
` ${color5.amber("?")} Restore all settings from this backup? ${color5.dim("[Y/n]")} `
|
|
1273
1457
|
)).trim().toLowerCase();
|
|
1274
1458
|
if (answer === "n" || answer === "no") return false;
|
|
1275
1459
|
try {
|
|
@@ -1279,12 +1463,12 @@ async function maybeRestoreDefaultProfileFromBackup(opts) {
|
|
|
1279
1463
|
profilePath: opts.profilePath
|
|
1280
1464
|
});
|
|
1281
1465
|
opts.renderer.write(
|
|
1282
|
-
` ${
|
|
1466
|
+
` ${color5.green("\u2713")} Restored all settings from ${color5.dim(backup.fileName)}
|
|
1283
1467
|
`
|
|
1284
1468
|
);
|
|
1285
1469
|
return true;
|
|
1286
1470
|
} catch (err) {
|
|
1287
|
-
opts.renderer.writeWarning(`Could not restore config backup: ${
|
|
1471
|
+
opts.renderer.writeWarning(`Could not restore config backup: ${toErrorMessage2(err)}
|
|
1288
1472
|
`);
|
|
1289
1473
|
return false;
|
|
1290
1474
|
}
|
|
@@ -1298,11 +1482,11 @@ import {
|
|
|
1298
1482
|
SYSTEM_PROMPT_VARIANT_OPTIONS,
|
|
1299
1483
|
SYSTEM_PROMPT_VARIANTS
|
|
1300
1484
|
} from "@wrongstack/core/agent";
|
|
1301
|
-
import { color as
|
|
1485
|
+
import { color as color9 } from "@wrongstack/core/utils";
|
|
1302
1486
|
|
|
1303
1487
|
// src/pre-launch/first-run.ts
|
|
1304
1488
|
import { hasProviderCredential } from "@wrongstack/core/models";
|
|
1305
|
-
import { color as
|
|
1489
|
+
import { color as color6, toErrorMessage as toErrorMessage3 } from "@wrongstack/core/utils";
|
|
1306
1490
|
import { PROVIDER_DEFINITIONS } from "@wrongstack/providers/definitions";
|
|
1307
1491
|
async function hasAnyCredential(config, modelsRegistry, env = process.env) {
|
|
1308
1492
|
for (const cfg of Object.values(config.providers ?? {})) {
|
|
@@ -1328,39 +1512,39 @@ function renderWelcome(renderer) {
|
|
|
1328
1512
|
renderer.write(`${boxTop("Welcome to WrongStack")}
|
|
1329
1513
|
`);
|
|
1330
1514
|
renderer.write(
|
|
1331
|
-
`${boxRow(
|
|
1515
|
+
`${boxRow(color6.dim("No model is connected yet. Pick how you want to connect one:"))}
|
|
1332
1516
|
`
|
|
1333
1517
|
);
|
|
1334
1518
|
renderer.write(`${boxDivider()}
|
|
1335
1519
|
`);
|
|
1336
1520
|
renderer.write(
|
|
1337
1521
|
`${boxRow(
|
|
1338
|
-
`${theme.accent("1")} ${
|
|
1522
|
+
`${theme.accent("1")} ${color6.bold("Sign in with a subscription")} ${color6.dim("ChatGPT \xB7 Claude \xB7 GitHub Copilot")}`
|
|
1339
1523
|
)}
|
|
1340
1524
|
`
|
|
1341
1525
|
);
|
|
1342
1526
|
renderer.write(
|
|
1343
1527
|
`${boxRow(
|
|
1344
|
-
`${theme.accent("2")} ${
|
|
1528
|
+
`${theme.accent("2")} ${color6.bold("Add an API key")} ${color6.dim("Anthropic \xB7 OpenAI \xB7 Google \xB7 OpenRouter \xB7 \u2026")}`
|
|
1345
1529
|
)}
|
|
1346
1530
|
`
|
|
1347
1531
|
);
|
|
1348
1532
|
renderer.write(
|
|
1349
1533
|
`${boxRow(
|
|
1350
|
-
`${theme.accent("3")} ${
|
|
1534
|
+
`${theme.accent("3")} ${color6.bold("Use a local server")} ${color6.dim("Ollama \xB7 LM Studio \xB7 vLLM \xB7 OmniRoute")}`
|
|
1351
1535
|
)}
|
|
1352
1536
|
`
|
|
1353
1537
|
);
|
|
1354
1538
|
renderer.write(
|
|
1355
1539
|
`${boxRow(
|
|
1356
|
-
`${theme.accent("4")} ${
|
|
1540
|
+
`${theme.accent("4")} ${color6.bold("Continue without a key")} ${color6.dim("setup mode \u2014 explore the app, no model")}`
|
|
1357
1541
|
)}
|
|
1358
1542
|
`
|
|
1359
1543
|
);
|
|
1360
1544
|
renderer.write(`${boxDivider()}
|
|
1361
1545
|
`);
|
|
1362
1546
|
renderer.write(
|
|
1363
|
-
`${boxRow(
|
|
1547
|
+
`${boxRow(color6.dim("You can change this any time with /auth inside the app, or `wstack auth`."))}
|
|
1364
1548
|
`
|
|
1365
1549
|
);
|
|
1366
1550
|
renderer.write(`${boxBottom()}
|
|
@@ -1379,12 +1563,12 @@ async function runFirstRunSetup(deps) {
|
|
|
1379
1563
|
renderWelcome(renderer);
|
|
1380
1564
|
const answer = (await reader.readLine(
|
|
1381
1565
|
`
|
|
1382
|
-
${
|
|
1566
|
+
${color6.amber("?")} Choose ${color6.dim("(1-4)")} ${color6.dim("[q to quit]")}: `
|
|
1383
1567
|
)).trim().toLowerCase();
|
|
1384
1568
|
if (!answer || answer === "q" || answer === "quit" || answer === "exit") {
|
|
1385
1569
|
renderer.write(
|
|
1386
1570
|
`
|
|
1387
|
-
${
|
|
1571
|
+
${color6.dim("No provider configured. Run")} ${color6.bold("wstack auth")} ${color6.dim("when you are ready.")}
|
|
1388
1572
|
|
|
1389
1573
|
`
|
|
1390
1574
|
);
|
|
@@ -1401,14 +1585,14 @@ ${color5.amber("?")} Choose ${color5.dim("(1-4)")} ${color5.dim("[q to quit]")}:
|
|
|
1401
1585
|
try {
|
|
1402
1586
|
await flow();
|
|
1403
1587
|
} catch (err) {
|
|
1404
|
-
renderer.writeWarning(`Setup step did not complete: ${
|
|
1588
|
+
renderer.writeWarning(`Setup step did not complete: ${toErrorMessage3(err)}
|
|
1405
1589
|
`);
|
|
1406
1590
|
}
|
|
1407
1591
|
let updated;
|
|
1408
1592
|
try {
|
|
1409
1593
|
updated = await deps.reloadConfig();
|
|
1410
1594
|
} catch (err) {
|
|
1411
|
-
renderer.writeWarning(`Could not re-read config: ${
|
|
1595
|
+
renderer.writeWarning(`Could not re-read config: ${toErrorMessage3(err)}
|
|
1412
1596
|
`);
|
|
1413
1597
|
continue;
|
|
1414
1598
|
}
|
|
@@ -1420,8 +1604,8 @@ ${color5.amber("?")} Choose ${color5.dim("(1-4)")} ${color5.dim("[q to quit]")}:
|
|
|
1420
1604
|
}
|
|
1421
1605
|
|
|
1422
1606
|
// src/pre-launch/launch-prompts.ts
|
|
1423
|
-
import * as
|
|
1424
|
-
import { atomicWrite as atomicWrite3, color as
|
|
1607
|
+
import * as fs5 from "node:fs/promises";
|
|
1608
|
+
import { atomicWrite as atomicWrite3, color as color7 } from "@wrongstack/core/utils";
|
|
1425
1609
|
var LaunchAbortedError = class extends Error {
|
|
1426
1610
|
exitCode = 0;
|
|
1427
1611
|
constructor() {
|
|
@@ -1452,19 +1636,19 @@ async function runLaunchPrompts(opts) {
|
|
|
1452
1636
|
yolo: yoloPinned ?? lastChoices.yolo,
|
|
1453
1637
|
autonomy: autonomyPinned ?? lastChoices.autonomy
|
|
1454
1638
|
};
|
|
1455
|
-
const onOff = (v) => v ?
|
|
1639
|
+
const onOff = (v) => v ? color7.green("on") : color7.dim("off");
|
|
1456
1640
|
const modeLabel = effective.mode.toUpperCase();
|
|
1457
1641
|
renderer.write(
|
|
1458
1642
|
`
|
|
1459
|
-
${
|
|
1643
|
+
${color7.dim("Last settings:")} ${color7.bold(modeLabel)} \xB7 YOLO ${onOff(effective.yolo)} \xB7 Autonomy ${effective.autonomy === "auto" ? color7.green("auto") : color7.dim("off")}
|
|
1460
1644
|
`
|
|
1461
1645
|
);
|
|
1462
1646
|
const answer = (await reader.readLine(
|
|
1463
|
-
` ${
|
|
1647
|
+
` ${color7.amber("?")} Continue with these? ${color7.dim("[Y/n/q]")} ${color7.dim("(auto Y in 5s)")} `,
|
|
1464
1648
|
{ timeoutMs: 5e3, defaultAnswer: "y" }
|
|
1465
1649
|
)).trim().toLowerCase();
|
|
1466
1650
|
if (answer === "q") {
|
|
1467
|
-
renderer.write(
|
|
1651
|
+
renderer.write(color7.dim(" Goodbye!\n"));
|
|
1468
1652
|
throw new LaunchAbortedError();
|
|
1469
1653
|
}
|
|
1470
1654
|
if (answer !== "n" && answer !== "no") {
|
|
@@ -1472,7 +1656,7 @@ async function runLaunchPrompts(opts) {
|
|
|
1472
1656
|
const badgeStr2 = badges2.length > 0 ? ` (${badges2.join(" \xB7 ")})` : "";
|
|
1473
1657
|
renderer.write(
|
|
1474
1658
|
`
|
|
1475
|
-
${
|
|
1659
|
+
${color7.green("\u25B6")} Launching in ${color7.bold(modeLabel)} mode${badgeStr2}
|
|
1476
1660
|
|
|
1477
1661
|
`
|
|
1478
1662
|
);
|
|
@@ -1485,10 +1669,10 @@ async function runLaunchPrompts(opts) {
|
|
|
1485
1669
|
} else {
|
|
1486
1670
|
const answer = (await reader.readLine(
|
|
1487
1671
|
`
|
|
1488
|
-
${
|
|
1672
|
+
${color7.amber("?")} Interactive mode: ${color7.bold("T")}UI / ${color7.bold("R")}EPL ${color7.dim("[T/r/q]")} `
|
|
1489
1673
|
)).trim().toLowerCase();
|
|
1490
1674
|
if (answer === "q") {
|
|
1491
|
-
renderer.write(
|
|
1675
|
+
renderer.write(color7.dim(" Goodbye!\n"));
|
|
1492
1676
|
throw new LaunchAbortedError();
|
|
1493
1677
|
}
|
|
1494
1678
|
mode = answer === "r" || answer === "repl" ? "repl" : "tui";
|
|
@@ -1498,10 +1682,10 @@ async function runLaunchPrompts(opts) {
|
|
|
1498
1682
|
yolo = yoloPinned;
|
|
1499
1683
|
} else {
|
|
1500
1684
|
const answer = (await reader.readLine(
|
|
1501
|
-
` ${
|
|
1685
|
+
` ${color7.amber("?")} YOLO mode ${color7.dim("(auto-approve tool calls)")} ${color7.dim("[Y/n/q]")} `
|
|
1502
1686
|
)).trim().toLowerCase();
|
|
1503
1687
|
if (answer === "q") {
|
|
1504
|
-
renderer.write(
|
|
1688
|
+
renderer.write(color7.dim(" Goodbye!\n"));
|
|
1505
1689
|
throw new LaunchAbortedError();
|
|
1506
1690
|
}
|
|
1507
1691
|
yolo = answer !== "n" && answer !== "no";
|
|
@@ -1511,10 +1695,10 @@ async function runLaunchPrompts(opts) {
|
|
|
1511
1695
|
autonomy = autonomyPinned;
|
|
1512
1696
|
} else {
|
|
1513
1697
|
const answer = (await reader.readLine(
|
|
1514
|
-
` ${
|
|
1698
|
+
` ${color7.amber("?")} Autonomy mode ${color7.dim("(auto-continue \u2014 agent picks next step)")} ${color7.dim("[Y/n/q]")} `
|
|
1515
1699
|
)).trim().toLowerCase();
|
|
1516
1700
|
if (answer === "q") {
|
|
1517
|
-
renderer.write(
|
|
1701
|
+
renderer.write(color7.dim(" Goodbye!\n"));
|
|
1518
1702
|
throw new LaunchAbortedError();
|
|
1519
1703
|
}
|
|
1520
1704
|
autonomy = answer !== "n" && answer !== "no" ? "auto" : "off";
|
|
@@ -1523,7 +1707,7 @@ async function runLaunchPrompts(opts) {
|
|
|
1523
1707
|
const badgeStr = badges.length > 0 ? ` (${badges.join(" \xB7 ")})` : "";
|
|
1524
1708
|
renderer.write(
|
|
1525
1709
|
`
|
|
1526
|
-
${
|
|
1710
|
+
${color7.green("\u25B6")} Launching in ${color7.bold(mode.toUpperCase())} mode${badgeStr}
|
|
1527
1711
|
|
|
1528
1712
|
`
|
|
1529
1713
|
);
|
|
@@ -1531,21 +1715,21 @@ async function runLaunchPrompts(opts) {
|
|
|
1531
1715
|
}
|
|
1532
1716
|
function buildBadges(chosen) {
|
|
1533
1717
|
const badges = [];
|
|
1534
|
-
if (chosen.yolo) badges.push(
|
|
1718
|
+
if (chosen.yolo) badges.push(color7.yellow("YOLO"));
|
|
1535
1719
|
if (chosen.autonomy !== "off")
|
|
1536
|
-
badges.push(
|
|
1720
|
+
badges.push(color7.magenta(`AUTONOMY:${chosen.autonomy.toUpperCase()}`));
|
|
1537
1721
|
return badges;
|
|
1538
1722
|
}
|
|
1539
1723
|
async function persistLaunchChoices(configPath, choices) {
|
|
1540
1724
|
let fileExists = false;
|
|
1541
1725
|
try {
|
|
1542
|
-
await
|
|
1726
|
+
await fs5.access(configPath);
|
|
1543
1727
|
fileExists = true;
|
|
1544
1728
|
} catch {
|
|
1545
1729
|
}
|
|
1546
1730
|
let existing = {};
|
|
1547
1731
|
try {
|
|
1548
|
-
const raw = await
|
|
1732
|
+
const raw = await fs5.readFile(configPath, "utf8");
|
|
1549
1733
|
existing = JSON.parse(raw);
|
|
1550
1734
|
} catch (err) {
|
|
1551
1735
|
if (fileExists) {
|
|
@@ -1565,9 +1749,9 @@ async function persistLaunchChoices(configPath, choices) {
|
|
|
1565
1749
|
}
|
|
1566
1750
|
|
|
1567
1751
|
// src/pre-launch/project-check.ts
|
|
1568
|
-
import * as
|
|
1569
|
-
import * as
|
|
1570
|
-
import { color as
|
|
1752
|
+
import * as fs6 from "node:fs/promises";
|
|
1753
|
+
import * as path7 from "node:path";
|
|
1754
|
+
import { color as color8, toErrorMessage as toErrorMessage4 } from "@wrongstack/core/utils";
|
|
1571
1755
|
var MANIFESTS = [
|
|
1572
1756
|
"package.json",
|
|
1573
1757
|
"pyproject.toml",
|
|
@@ -1582,13 +1766,13 @@ var MANIFESTS = [
|
|
|
1582
1766
|
];
|
|
1583
1767
|
async function detectProjectKind(projectRoot) {
|
|
1584
1768
|
try {
|
|
1585
|
-
await
|
|
1769
|
+
await fs6.access(path7.join(projectRoot, ".wrongstack", "AGENTS.md"));
|
|
1586
1770
|
return "initialized";
|
|
1587
1771
|
} catch {
|
|
1588
1772
|
}
|
|
1589
1773
|
for (const m of MANIFESTS) {
|
|
1590
1774
|
try {
|
|
1591
|
-
await
|
|
1775
|
+
await fs6.access(path7.join(projectRoot, m));
|
|
1592
1776
|
return "project";
|
|
1593
1777
|
} catch {
|
|
1594
1778
|
}
|
|
@@ -1596,12 +1780,12 @@ async function detectProjectKind(projectRoot) {
|
|
|
1596
1780
|
return "empty";
|
|
1597
1781
|
}
|
|
1598
1782
|
async function scaffoldAgentsMd(projectRoot) {
|
|
1599
|
-
const dir =
|
|
1600
|
-
const file =
|
|
1783
|
+
const dir = path7.join(projectRoot, ".wrongstack");
|
|
1784
|
+
const file = path7.join(dir, "AGENTS.md");
|
|
1601
1785
|
const facts = await detectProjectFacts(projectRoot);
|
|
1602
1786
|
const body = renderAgentsTemplate(facts);
|
|
1603
|
-
await
|
|
1604
|
-
await
|
|
1787
|
+
await fs6.mkdir(dir, { recursive: true });
|
|
1788
|
+
await fs6.writeFile(file, body, "utf8");
|
|
1605
1789
|
return file;
|
|
1606
1790
|
}
|
|
1607
1791
|
async function runProjectCheck(opts) {
|
|
@@ -1610,7 +1794,7 @@ async function runProjectCheck(opts) {
|
|
|
1610
1794
|
if (kind === "initialized") {
|
|
1611
1795
|
renderer.write(
|
|
1612
1796
|
`
|
|
1613
|
-
${
|
|
1797
|
+
${color8.green("\u2713")} Project initialized ${color8.dim(`(${path7.join(projectRoot, ".wrongstack", "AGENTS.md")})`)}
|
|
1614
1798
|
`
|
|
1615
1799
|
);
|
|
1616
1800
|
return true;
|
|
@@ -1618,51 +1802,51 @@ async function runProjectCheck(opts) {
|
|
|
1618
1802
|
if (kind === "project") {
|
|
1619
1803
|
renderer.write(
|
|
1620
1804
|
`
|
|
1621
|
-
${
|
|
1805
|
+
${color8.amber("\u25CF")} Project detected ${color8.dim(`(${projectRoot})`)} but ${color8.bold(".wrongstack/AGENTS.md")} is missing.
|
|
1622
1806
|
`
|
|
1623
1807
|
);
|
|
1624
1808
|
const answer2 = (await reader.readLine(
|
|
1625
|
-
` ${
|
|
1809
|
+
` ${color8.amber("?")} Scaffold ${color8.bold("AGENTS.md")} now? ${color8.dim("[y/N/q]")} `
|
|
1626
1810
|
)).trim().toLowerCase();
|
|
1627
1811
|
if (answer2 === "q") {
|
|
1628
|
-
renderer.write(
|
|
1812
|
+
renderer.write(color8.dim(" Cancelled.\n"));
|
|
1629
1813
|
return false;
|
|
1630
1814
|
}
|
|
1631
1815
|
if (answer2 === "y" || answer2 === "yes") {
|
|
1632
1816
|
try {
|
|
1633
1817
|
const file = await scaffoldAgentsMd(projectRoot);
|
|
1634
|
-
renderer.write(` ${
|
|
1818
|
+
renderer.write(` ${color8.green("\u2713")} Wrote ${color8.dim(file)}
|
|
1635
1819
|
`);
|
|
1636
1820
|
} catch (err) {
|
|
1637
|
-
renderer.writeError(`Failed to scaffold AGENTS.md: ${
|
|
1821
|
+
renderer.writeError(`Failed to scaffold AGENTS.md: ${toErrorMessage4(err)}`);
|
|
1638
1822
|
}
|
|
1639
1823
|
}
|
|
1640
1824
|
return true;
|
|
1641
1825
|
}
|
|
1642
|
-
const gitDir =
|
|
1826
|
+
const gitDir = path7.join(projectRoot, ".git");
|
|
1643
1827
|
let hasGit = false;
|
|
1644
1828
|
try {
|
|
1645
|
-
await
|
|
1829
|
+
await fs6.access(gitDir);
|
|
1646
1830
|
hasGit = true;
|
|
1647
1831
|
} catch {
|
|
1648
1832
|
}
|
|
1649
1833
|
if (!hasGit) {
|
|
1650
1834
|
renderer.write(
|
|
1651
1835
|
`
|
|
1652
|
-
${
|
|
1836
|
+
${color8.dim("\u25CB")} ${color8.dim(`No project manifest in ${projectRoot} \u2014 running in a scratch directory.`)}
|
|
1653
1837
|
`
|
|
1654
1838
|
);
|
|
1655
1839
|
const answer2 = (await reader.readLine(
|
|
1656
|
-
` ${
|
|
1840
|
+
` ${color8.amber("?")} No git repo found. ${color8.bold("Initialize git?")} ${color8.dim("[y/N/q]")} `
|
|
1657
1841
|
)).trim().toLowerCase();
|
|
1658
1842
|
if (answer2 === "q") {
|
|
1659
|
-
renderer.write(
|
|
1843
|
+
renderer.write(color8.dim(" Cancelled.\n"));
|
|
1660
1844
|
return false;
|
|
1661
1845
|
}
|
|
1662
1846
|
if (answer2 === "y" || answer2 === "yes") {
|
|
1663
1847
|
try {
|
|
1664
1848
|
const { spawn: spawn2 } = await import("node:child_process");
|
|
1665
|
-
await new Promise((
|
|
1849
|
+
await new Promise((resolve3, reject) => {
|
|
1666
1850
|
const child = spawn2("git", ["init"], {
|
|
1667
1851
|
cwd,
|
|
1668
1852
|
signal: AbortSignal.timeout(1e4),
|
|
@@ -1671,26 +1855,26 @@ async function runProjectCheck(opts) {
|
|
|
1671
1855
|
child.on("error", reject);
|
|
1672
1856
|
child.on(
|
|
1673
1857
|
"close",
|
|
1674
|
-
(code) => code === 0 ?
|
|
1858
|
+
(code) => code === 0 ? resolve3() : reject(new Error(`git init failed with ${code}`))
|
|
1675
1859
|
);
|
|
1676
1860
|
});
|
|
1677
|
-
renderer.write(` ${
|
|
1861
|
+
renderer.write(` ${color8.green("\u2713")} Git repository initialized
|
|
1678
1862
|
`);
|
|
1679
1863
|
} catch (err) {
|
|
1680
|
-
renderer.writeError(`git init failed: ${
|
|
1864
|
+
renderer.writeError(`git init failed: ${toErrorMessage4(err)}
|
|
1681
1865
|
`);
|
|
1682
1866
|
}
|
|
1683
1867
|
}
|
|
1684
1868
|
} else {
|
|
1685
1869
|
renderer.write(
|
|
1686
1870
|
`
|
|
1687
|
-
${
|
|
1871
|
+
${color8.dim("\u25CB")} ${color8.dim(`No project manifest in ${projectRoot} \u2014 running in a scratch directory.`)}
|
|
1688
1872
|
`
|
|
1689
1873
|
);
|
|
1690
1874
|
}
|
|
1691
|
-
const answer = (await reader.readLine(` ${
|
|
1875
|
+
const answer = (await reader.readLine(` ${color8.amber("?")} Continue anyway? ${color8.dim("[Y/n/q]")} `)).trim().toLowerCase();
|
|
1692
1876
|
if (answer === "q" || answer === "n" || answer === "no") {
|
|
1693
|
-
renderer.write(
|
|
1877
|
+
renderer.write(color8.dim(" Cancelled.\n"));
|
|
1694
1878
|
return false;
|
|
1695
1879
|
}
|
|
1696
1880
|
return true;
|
|
@@ -1725,28 +1909,28 @@ async function runSystemPromptMenu(deps) {
|
|
|
1725
1909
|
const defaultVariant = lastVariant ?? "default";
|
|
1726
1910
|
if (lastVariant) {
|
|
1727
1911
|
const answer2 = (await reader.readLine(
|
|
1728
|
-
` ${
|
|
1912
|
+
` ${color9.amber("?")} Continue with ${color9.bold(labelFor(lastVariant))} system prompt ${color9.dim(`(~${fmtTok(tokens[lastVariant])} tokens)`)}? ${color9.dim("[Y/n/q]")} ${color9.dim("(auto Y in 5s)")} `,
|
|
1729
1913
|
{ timeoutMs: SUMMARY_TIMEOUT_MS2, defaultAnswer: "y" }
|
|
1730
1914
|
)).trim().toLowerCase();
|
|
1731
1915
|
if (answer2 === "q" || answer2 === "quit") throw new LaunchAbortedError();
|
|
1732
1916
|
if (answer2 !== "n" && answer2 !== "no") return lastVariant;
|
|
1733
1917
|
}
|
|
1734
1918
|
renderer.write(`
|
|
1735
|
-
${
|
|
1919
|
+
${color9.amber("?")} System prompt:
|
|
1736
1920
|
`);
|
|
1737
1921
|
for (const [index, opt] of SYSTEM_PROMPT_OPTIONS.entries()) {
|
|
1738
1922
|
const num2 = index + 1;
|
|
1739
1923
|
const isDefault = opt.variant === defaultVariant;
|
|
1740
|
-
const marker = isDefault ?
|
|
1741
|
-
const label = isDefault ?
|
|
1924
|
+
const marker = isDefault ? color9.cyan("\u25CF") : color9.dim("\u25CB");
|
|
1925
|
+
const label = isDefault ? color9.bold(opt.label) : opt.label;
|
|
1742
1926
|
renderer.write(
|
|
1743
|
-
` ${
|
|
1927
|
+
` ${color9.dim(`${num2}.`)} ${marker} ${label.padEnd(9)} ${color9.dim(`~${fmtTok(tokens[opt.variant])} tokens`)} ${color9.dim(opt.hint)}
|
|
1744
1928
|
`
|
|
1745
1929
|
);
|
|
1746
1930
|
}
|
|
1747
1931
|
const answer = (await reader.readLine(
|
|
1748
1932
|
`
|
|
1749
|
-
${
|
|
1933
|
+
${color9.amber("?")} Select system prompt ${color9.dim(`[1-${SYSTEM_PROMPT_OPTIONS.length}, Enter = ${labelFor(defaultVariant)}, q to quit]`)}: `
|
|
1750
1934
|
)).trim().toLowerCase();
|
|
1751
1935
|
if (answer === "q" || answer === "quit") throw new LaunchAbortedError();
|
|
1752
1936
|
if (!answer) return defaultVariant;
|
|
@@ -1803,8 +1987,8 @@ async function bootConfig(flags) {
|
|
|
1803
1987
|
}
|
|
1804
1988
|
|
|
1805
1989
|
// src/input-reader.ts
|
|
1806
|
-
import * as
|
|
1807
|
-
import * as
|
|
1990
|
+
import * as fs7 from "node:fs/promises";
|
|
1991
|
+
import * as path8 from "node:path";
|
|
1808
1992
|
import * as readline from "node:readline";
|
|
1809
1993
|
import {
|
|
1810
1994
|
resolveWstackPaths,
|
|
@@ -1823,7 +2007,7 @@ var ReadlineInputReader = class {
|
|
|
1823
2007
|
}
|
|
1824
2008
|
async loadHistory() {
|
|
1825
2009
|
try {
|
|
1826
|
-
const raw = await
|
|
2010
|
+
const raw = await fs7.readFile(this.historyFile, "utf8");
|
|
1827
2011
|
this.history = raw.split("\n").filter(Boolean).slice(-1e3);
|
|
1828
2012
|
} catch {
|
|
1829
2013
|
this.history = [];
|
|
@@ -1831,8 +2015,8 @@ var ReadlineInputReader = class {
|
|
|
1831
2015
|
}
|
|
1832
2016
|
async saveHistory() {
|
|
1833
2017
|
try {
|
|
1834
|
-
await
|
|
1835
|
-
await
|
|
2018
|
+
await fs7.mkdir(path8.dirname(this.historyFile), { recursive: true });
|
|
2019
|
+
await fs7.writeFile(this.historyFile, this.history.slice(-1e3).join("\n"));
|
|
1836
2020
|
} catch {
|
|
1837
2021
|
}
|
|
1838
2022
|
}
|
|
@@ -1853,25 +2037,25 @@ var ReadlineInputReader = class {
|
|
|
1853
2037
|
async readLine(prompt, timeoutOpts) {
|
|
1854
2038
|
if (this.history.length === 0) await this.loadHistory();
|
|
1855
2039
|
while (this.pending) {
|
|
1856
|
-
await new Promise((
|
|
2040
|
+
await new Promise((resolve3) => setTimeout(resolve3, 50));
|
|
1857
2041
|
}
|
|
1858
2042
|
this.pending = true;
|
|
1859
2043
|
try {
|
|
1860
2044
|
if (this.rl) {
|
|
1861
2045
|
const old = this.rl;
|
|
1862
2046
|
this.rl = void 0;
|
|
1863
|
-
await new Promise((
|
|
2047
|
+
await new Promise((resolve3) => {
|
|
1864
2048
|
if (old.closed) {
|
|
1865
|
-
|
|
2049
|
+
resolve3();
|
|
1866
2050
|
} else {
|
|
1867
|
-
old.once("close",
|
|
2051
|
+
old.once("close", resolve3);
|
|
1868
2052
|
old.close();
|
|
1869
2053
|
}
|
|
1870
2054
|
});
|
|
1871
2055
|
}
|
|
1872
2056
|
const fresh = this.ensure();
|
|
1873
2057
|
this.installPromptGuard(fresh);
|
|
1874
|
-
const line = await new Promise((
|
|
2058
|
+
const line = await new Promise((resolve3) => {
|
|
1875
2059
|
let settled = false;
|
|
1876
2060
|
let timeoutHandle;
|
|
1877
2061
|
const settle = (line2) => {
|
|
@@ -1879,7 +2063,7 @@ var ReadlineInputReader = class {
|
|
|
1879
2063
|
settled = true;
|
|
1880
2064
|
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
1881
2065
|
setOutputLineGuard(null);
|
|
1882
|
-
|
|
2066
|
+
resolve3(line2);
|
|
1883
2067
|
};
|
|
1884
2068
|
if (timeoutOpts) {
|
|
1885
2069
|
timeoutHandle = setTimeout(() => {
|
|
@@ -1946,7 +2130,7 @@ var ReadlineInputReader = class {
|
|
|
1946
2130
|
const signal = opts.signal;
|
|
1947
2131
|
if (signal?.aborted) return "";
|
|
1948
2132
|
writeOut(prompt);
|
|
1949
|
-
return new Promise((
|
|
2133
|
+
return new Promise((resolve3) => {
|
|
1950
2134
|
const stdin = process.stdin;
|
|
1951
2135
|
const wasRaw = stdin.isRaw;
|
|
1952
2136
|
const wasPaused = stdin.isPaused();
|
|
@@ -1957,7 +2141,7 @@ var ReadlineInputReader = class {
|
|
|
1957
2141
|
if (key === "") {
|
|
1958
2142
|
cleanup();
|
|
1959
2143
|
writeOut("\n");
|
|
1960
|
-
|
|
2144
|
+
resolve3("");
|
|
1961
2145
|
return;
|
|
1962
2146
|
}
|
|
1963
2147
|
const opt = options.find(
|
|
@@ -1967,17 +2151,17 @@ var ReadlineInputReader = class {
|
|
|
1967
2151
|
cleanup();
|
|
1968
2152
|
writeOut(`${opt.key}
|
|
1969
2153
|
`);
|
|
1970
|
-
|
|
2154
|
+
resolve3(opt.value);
|
|
1971
2155
|
}
|
|
1972
2156
|
};
|
|
1973
2157
|
const onClose = () => {
|
|
1974
2158
|
cleanup();
|
|
1975
|
-
|
|
2159
|
+
resolve3("");
|
|
1976
2160
|
};
|
|
1977
2161
|
const onAbort = () => {
|
|
1978
2162
|
cleanup();
|
|
1979
2163
|
writeOut("\n");
|
|
1980
|
-
|
|
2164
|
+
resolve3("");
|
|
1981
2165
|
};
|
|
1982
2166
|
const cleanup = () => {
|
|
1983
2167
|
stdin.off("data", onData);
|
|
@@ -2011,7 +2195,7 @@ var ReadlineInputReader = class {
|
|
|
2011
2195
|
this.rl?.close();
|
|
2012
2196
|
this.rl = void 0;
|
|
2013
2197
|
writeOut(prompt);
|
|
2014
|
-
return new Promise((
|
|
2198
|
+
return new Promise((resolve3) => {
|
|
2015
2199
|
let buf = "";
|
|
2016
2200
|
const wasRaw = stdin.isRaw;
|
|
2017
2201
|
const cleanup = () => {
|
|
@@ -2040,13 +2224,13 @@ var ReadlineInputReader = class {
|
|
|
2040
2224
|
cleanup();
|
|
2041
2225
|
writeOut(` ${dim(`[${buf.length} chars]`)}
|
|
2042
2226
|
`);
|
|
2043
|
-
|
|
2227
|
+
resolve3(buf);
|
|
2044
2228
|
return;
|
|
2045
2229
|
}
|
|
2046
2230
|
if (ch === "") {
|
|
2047
2231
|
cleanup();
|
|
2048
2232
|
writeOut("\n");
|
|
2049
|
-
|
|
2233
|
+
resolve3("");
|
|
2050
2234
|
return;
|
|
2051
2235
|
}
|
|
2052
2236
|
if (ch === "") {
|
|
@@ -2089,7 +2273,7 @@ function dim(s) {
|
|
|
2089
2273
|
}
|
|
2090
2274
|
|
|
2091
2275
|
// src/renderer.ts
|
|
2092
|
-
import { color as
|
|
2276
|
+
import { color as color10 } from "@wrongstack/core/utils";
|
|
2093
2277
|
var TerminalRenderer = class _TerminalRenderer {
|
|
2094
2278
|
out;
|
|
2095
2279
|
err;
|
|
@@ -2202,7 +2386,7 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2202
2386
|
if (!this.lineStart) this.out.write("\n");
|
|
2203
2387
|
const arrow = theme2.primary("\u2192");
|
|
2204
2388
|
const display = formatInputSummary(input);
|
|
2205
|
-
this.out.write(`${arrow} ${theme2.bold(name)}${display ?
|
|
2389
|
+
this.out.write(`${arrow} ${theme2.bold(name)}${display ? color10.dim(` ${display}`) : ""}
|
|
2206
2390
|
`);
|
|
2207
2391
|
this.lineStart = true;
|
|
2208
2392
|
}
|
|
@@ -2219,7 +2403,7 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2219
2403
|
if (isError) {
|
|
2220
2404
|
const firstLine = txt.split("\n")[0] ?? "";
|
|
2221
2405
|
const truncated = firstLine.length > 200 ? `${firstLine.slice(0, 197)}\u2026` : firstLine;
|
|
2222
|
-
this.out.write(` ${prefix} ${
|
|
2406
|
+
this.out.write(` ${prefix} ${color10.dim(truncated)}
|
|
2223
2407
|
`);
|
|
2224
2408
|
this.lineStart = true;
|
|
2225
2409
|
return;
|
|
@@ -2227,7 +2411,7 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2227
2411
|
const isEditLike = name === "edit" || name === "write";
|
|
2228
2412
|
const diff = extractDiff(content);
|
|
2229
2413
|
if (isEditLike && diff) {
|
|
2230
|
-
this.out.write(` ${prefix} ${
|
|
2414
|
+
this.out.write(` ${prefix} ${color10.dim(summarize(content, name))}
|
|
2231
2415
|
`);
|
|
2232
2416
|
const rendered = renderDiff(diff).split("\n").map((l) => ` ${l}`).join("\n");
|
|
2233
2417
|
this.out.write(`${rendered}
|
|
@@ -2238,7 +2422,7 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2238
2422
|
const summary = summarize(content, name);
|
|
2239
2423
|
const isReadLike = name === "read" || name === "grep" || name === "glob" || name === "bash" || name === "exec";
|
|
2240
2424
|
if (renderMode === "simple") {
|
|
2241
|
-
this.out.write(` ${prefix} ${
|
|
2425
|
+
this.out.write(` ${prefix} ${color10.dim(summary || compactSingleLine(bodyText))}
|
|
2242
2426
|
`);
|
|
2243
2427
|
this.lineStart = true;
|
|
2244
2428
|
return;
|
|
@@ -2247,16 +2431,16 @@ var TerminalRenderer = class _TerminalRenderer {
|
|
|
2247
2431
|
const lines = bodyText.split("\n");
|
|
2248
2432
|
const head = lines.slice(0, previewLines).map((l) => l.replace(/\s+$/, ""));
|
|
2249
2433
|
const moreCount = Math.max(0, lines.length - head.length);
|
|
2250
|
-
this.out.write(` ${prefix} ${
|
|
2434
|
+
this.out.write(` ${prefix} ${color10.dim(summary)}
|
|
2251
2435
|
`);
|
|
2252
2436
|
for (const l of head) {
|
|
2253
2437
|
const capped = l.length > 200 ? `${l.slice(0, 197)}\u2026` : l;
|
|
2254
|
-
this.out.write(` ${
|
|
2438
|
+
this.out.write(` ${color10.dim(capped)}
|
|
2255
2439
|
`);
|
|
2256
2440
|
}
|
|
2257
2441
|
if (moreCount > 0) {
|
|
2258
2442
|
this.out.write(
|
|
2259
|
-
` ${
|
|
2443
|
+
` ${color10.dim(`+${moreCount} more line${moreCount === 1 ? "" : "s"}`)}
|
|
2260
2444
|
`
|
|
2261
2445
|
);
|
|
2262
2446
|
}
|
|
@@ -2395,7 +2579,7 @@ function renderMarkdown(s) {
|
|
|
2395
2579
|
return theme2.primary(theme2.bold(`${hashes} ${text}`));
|
|
2396
2580
|
});
|
|
2397
2581
|
out = out.replace(/```([a-zA-Z0-9_+-]*)\n([\s\S]*?)```/g, (_m, _lang, code) => {
|
|
2398
|
-
return
|
|
2582
|
+
return color10.gray(`
|
|
2399
2583
|
\u250C\u2500
|
|
2400
2584
|
${code.replace(/^/gm, "\u2502 ")}\u2514\u2500`);
|
|
2401
2585
|
});
|
|
@@ -2403,7 +2587,7 @@ ${code.replace(/^/gm, "\u2502 ")}\u2514\u2500`);
|
|
|
2403
2587
|
out = out.replace(/\*\*([^*]+)\*\*/g, (_m, text) => theme2.bold(text));
|
|
2404
2588
|
out = out.replace(
|
|
2405
2589
|
/(^|[^*])\*([^*\n]+)\*([^*]|$)/g,
|
|
2406
|
-
(_m, l, t, r) => `${l}${
|
|
2590
|
+
(_m, l, t, r) => `${l}${color10.italic(t)}${r}`
|
|
2407
2591
|
);
|
|
2408
2592
|
return out;
|
|
2409
2593
|
}
|
|
@@ -2496,14 +2680,14 @@ function summarize(value, name) {
|
|
|
2496
2680
|
if (typeof v === "object" && v !== null) {
|
|
2497
2681
|
const o = v;
|
|
2498
2682
|
if (name === "edit") {
|
|
2499
|
-
const
|
|
2683
|
+
const path10 = typeof o["path"] === "string" ? o["path"] : "";
|
|
2500
2684
|
const reps = typeof o["replacements"] === "number" ? o["replacements"] : 0;
|
|
2501
|
-
return `${
|
|
2685
|
+
return `${path10} ${reps} replacement${reps === 1 ? "" : "s"}`.trim();
|
|
2502
2686
|
}
|
|
2503
2687
|
if (name === "write") {
|
|
2504
|
-
const
|
|
2688
|
+
const path10 = typeof o["path"] === "string" ? o["path"] : "";
|
|
2505
2689
|
const bytes = typeof o["bytes"] === "number" ? o["bytes"] : void 0;
|
|
2506
|
-
return bytes !== void 0 ? `${
|
|
2690
|
+
return bytes !== void 0 ? `${path10} ${bytes}B` : path10;
|
|
2507
2691
|
}
|
|
2508
2692
|
if (name === "read") {
|
|
2509
2693
|
return summarizeRead(o);
|
|
@@ -2521,13 +2705,13 @@ function summarize(value, name) {
|
|
|
2521
2705
|
return "";
|
|
2522
2706
|
}
|
|
2523
2707
|
function summarizeRead(o) {
|
|
2524
|
-
const
|
|
2708
|
+
const path10 = typeof o["path"] === "string" ? o["path"] : "";
|
|
2525
2709
|
const total = typeof o["total_lines"] === "number" ? o["total_lines"] : void 0;
|
|
2526
2710
|
const truncated = o["truncated"] === true;
|
|
2527
2711
|
const cached = o["cached"] === true;
|
|
2528
2712
|
const note = typeof o["note"] === "string" ? o["note"] : void 0;
|
|
2529
2713
|
const parts = [];
|
|
2530
|
-
if (
|
|
2714
|
+
if (path10) parts.push(path10);
|
|
2531
2715
|
if (total !== void 0) parts.push(`${total} line${total === 1 ? "" : "s"}`);
|
|
2532
2716
|
const flags = [];
|
|
2533
2717
|
if (truncated) flags.push("truncated");
|
|
@@ -2575,86 +2759,6 @@ function compactSingleLine(text) {
|
|
|
2575
2759
|
|
|
2576
2760
|
// src/boot.ts
|
|
2577
2761
|
var GITHUB_PROVIDERS_OVERLAY_URL = "https://raw.githubusercontent.com/WrongStack/WrongStack/main/packages/cli/data/providers.json";
|
|
2578
|
-
function resolveBundledOverlayFile() {
|
|
2579
|
-
try {
|
|
2580
|
-
return fileURLToPath(
|
|
2581
|
-
new URL("../data/providers.json", moduleUrlFor(import.meta.url, "@wrongstack/cli"))
|
|
2582
|
-
);
|
|
2583
|
-
} catch {
|
|
2584
|
-
return void 0;
|
|
2585
|
-
}
|
|
2586
|
-
}
|
|
2587
|
-
async function validateSavedProviderModel(config, modelsRegistry) {
|
|
2588
|
-
const providerId = config.provider;
|
|
2589
|
-
const modelId = config.model;
|
|
2590
|
-
if (!providerId || !modelId) return { ok: false, reason: "missing provider/model" };
|
|
2591
|
-
if (isSetupProvider(providerId)) return { ok: true };
|
|
2592
|
-
const saved = config.providers?.[providerId];
|
|
2593
|
-
const lookupId = saved?.type && saved.type !== providerId ? saved.type : providerId;
|
|
2594
|
-
const catalogProvider = await modelsRegistry.getProvider(lookupId).catch(() => void 0);
|
|
2595
|
-
if (!catalogProvider && !saved?.family)
|
|
2596
|
-
return { ok: false, reason: `provider "${providerId}" is no longer available` };
|
|
2597
|
-
const hasCredential = (catalogProvider?.envVars ?? saved?.envVars ?? []).some(
|
|
2598
|
-
(envVar) => Boolean(process.env[envVar])
|
|
2599
|
-
) || saved !== void 0 && resolveActiveApiKey(saved) !== void 0 || isKeylessLocalProvider({
|
|
2600
|
-
apiBase: saved?.baseUrl ?? catalogProvider?.apiBase,
|
|
2601
|
-
envVars: saved?.envVars ?? catalogProvider?.envVars
|
|
2602
|
-
});
|
|
2603
|
-
if (!hasCredential) return { ok: false, reason: `provider "${providerId}" has no usable key` };
|
|
2604
|
-
const visible = visibleModelIds(
|
|
2605
|
-
providerId,
|
|
2606
|
-
config,
|
|
2607
|
-
(catalogProvider?.models ?? []).map((m) => m.id),
|
|
2608
|
-
saved
|
|
2609
|
-
);
|
|
2610
|
-
if (visible.length > 0 && !visible.includes(modelId)) {
|
|
2611
|
-
return {
|
|
2612
|
-
ok: false,
|
|
2613
|
-
reason: `model "${modelId}" is no longer available for provider "${providerId}"`
|
|
2614
|
-
};
|
|
2615
|
-
}
|
|
2616
|
-
return { ok: true };
|
|
2617
|
-
}
|
|
2618
|
-
async function autoSelectSavedProvider(config, modelsRegistry) {
|
|
2619
|
-
const providers = config.providers ?? {};
|
|
2620
|
-
const entries = config.provider && providers[config.provider] ? [[config.provider, providers[config.provider]]] : Object.entries(providers);
|
|
2621
|
-
for (const [id, cfg] of entries) {
|
|
2622
|
-
if (!cfg) continue;
|
|
2623
|
-
let model = cfg.models?.[0];
|
|
2624
|
-
if (!model) {
|
|
2625
|
-
const catalogId = cfg.type && cfg.type !== id ? cfg.type : id;
|
|
2626
|
-
const catalog = await modelsRegistry.getProvider(catalogId).catch(() => void 0);
|
|
2627
|
-
model = catalog?.models?.[0]?.id;
|
|
2628
|
-
}
|
|
2629
|
-
if (model) return { provider: id, model };
|
|
2630
|
-
}
|
|
2631
|
-
return void 0;
|
|
2632
|
-
}
|
|
2633
|
-
function resolveBundledSkillsDir2() {
|
|
2634
|
-
try {
|
|
2635
|
-
const req = createRequire4(import.meta.url);
|
|
2636
|
-
const corePkg = wrongstackPackageJsonPath3("@wrongstack/core", (id) => req.resolve(id));
|
|
2637
|
-
return path7.join(path7.dirname(corePkg), "skills");
|
|
2638
|
-
} catch {
|
|
2639
|
-
return void 0;
|
|
2640
|
-
}
|
|
2641
|
-
}
|
|
2642
|
-
function resolveBundledPromptsDir2() {
|
|
2643
|
-
try {
|
|
2644
|
-
const req = createRequire4(import.meta.url);
|
|
2645
|
-
const corePkg = wrongstackPackageJsonPath3("@wrongstack/core", (id) => req.resolve(id));
|
|
2646
|
-
return path7.join(path7.dirname(corePkg), "data", "prompts");
|
|
2647
|
-
} catch {
|
|
2648
|
-
return void 0;
|
|
2649
|
-
}
|
|
2650
|
-
}
|
|
2651
|
-
function isHomeDirectory(cwd, userHome) {
|
|
2652
|
-
if (!cwd || !userHome) return false;
|
|
2653
|
-
return path7.resolve(cwd) === path7.resolve(userHome);
|
|
2654
|
-
}
|
|
2655
|
-
function shouldPrintYoloNotice(lastChoices, yoloPinned, yolo) {
|
|
2656
|
-
return !lastChoices && yoloPinned === void 0 && yolo;
|
|
2657
|
-
}
|
|
2658
2762
|
async function boot(argv) {
|
|
2659
2763
|
const { flags, positional } = parseArgs(argv);
|
|
2660
2764
|
if (positional[0] === "update") {
|
|
@@ -2666,6 +2770,14 @@ async function boot(argv) {
|
|
|
2666
2770
|
flags
|
|
2667
2771
|
});
|
|
2668
2772
|
}
|
|
2773
|
+
if (positional[0] === "remote" || typeof flags["remote"] === "string") {
|
|
2774
|
+
const { runRemoteCommand } = await import("./remote-O5WXHLWV.js");
|
|
2775
|
+
return runRemoteCommand(
|
|
2776
|
+
positional[0] === "remote" ? positional.slice(1) : positional,
|
|
2777
|
+
flags,
|
|
2778
|
+
new TerminalRenderer()
|
|
2779
|
+
);
|
|
2780
|
+
}
|
|
2669
2781
|
if (positional[0] === "resume" && positional[1] && !subcommands["__noop_resume_marker"]) {
|
|
2670
2782
|
flags["resume"] = positional[1];
|
|
2671
2783
|
positional.splice(0, 2);
|
|
@@ -2674,14 +2786,34 @@ async function boot(argv) {
|
|
|
2674
2786
|
try {
|
|
2675
2787
|
bootResult = await bootConfig(flags);
|
|
2676
2788
|
} catch (err) {
|
|
2677
|
-
writeErr(`Config error: ${
|
|
2789
|
+
writeErr(`Config error: ${toErrorMessage5(err)}
|
|
2678
2790
|
`);
|
|
2679
2791
|
return 2;
|
|
2680
2792
|
}
|
|
2681
2793
|
let { paths, config, vault } = bootResult;
|
|
2794
|
+
try {
|
|
2795
|
+
resolveToolRestriction(flags);
|
|
2796
|
+
resolveLaunchAllowedTools(flags);
|
|
2797
|
+
parseOutputFormat(flags["output-format"]);
|
|
2798
|
+
announceSafeMode(flags, writeErr);
|
|
2799
|
+
activateRestrictedMode(flags, writeErr);
|
|
2800
|
+
const launchMcp = await resolveLaunchMcpServers(flags, paths.cwd);
|
|
2801
|
+
if (launchMcp) flags["mcp-config"] = JSON.stringify({ mcpServers: launchMcp });
|
|
2802
|
+
const schema = await resolveJsonSchemaFlag(flags["json-schema"], paths.cwd);
|
|
2803
|
+
if (schema) flags["json-schema"] = JSON.stringify(schema);
|
|
2804
|
+
const appended = await resolveAppendedSystemPrompt(flags, paths.cwd);
|
|
2805
|
+
delete flags["append-system-prompt-file"];
|
|
2806
|
+
if (appended) flags["append-system-prompt"] = appended;
|
|
2807
|
+
else delete flags["append-system-prompt"];
|
|
2808
|
+
} catch (err) {
|
|
2809
|
+
writeErr(`wstack: ${toErrorMessage5(err)}
|
|
2810
|
+
`);
|
|
2811
|
+
return 2;
|
|
2812
|
+
}
|
|
2682
2813
|
let first = positional[0];
|
|
2683
2814
|
const mayOfferConfigRecovery = isStdinTTY2() && (positional.length === 0 || first === "quick") && typeof flags["prompt"] !== "string" && !flags["webui"] && !flags["no-interactive"] && !flags["skip"];
|
|
2684
|
-
const
|
|
2815
|
+
const machineOutput = flags["output-json"] === true || flags["output-format"] === "json" || flags["output-format"] === "stream-json";
|
|
2816
|
+
const renderer = new TerminalRenderer(machineOutput ? { out: process.stderr } : void 0);
|
|
2685
2817
|
const reader = new ReadlineInputReader({ historyFile: paths.wpaths.historyFile });
|
|
2686
2818
|
if (mayOfferConfigRecovery) {
|
|
2687
2819
|
const recoveryProfile = config.activeProfile ?? "default";
|
|
@@ -2697,7 +2829,7 @@ async function boot(argv) {
|
|
|
2697
2829
|
bootResult = await bootConfig(flags);
|
|
2698
2830
|
({ paths, config, vault } = bootResult);
|
|
2699
2831
|
} catch (err) {
|
|
2700
|
-
writeErr(`Config error after backup restore: ${
|
|
2832
|
+
writeErr(`Config error after backup restore: ${toErrorMessage5(err)}
|
|
2701
2833
|
`);
|
|
2702
2834
|
await reader.close();
|
|
2703
2835
|
return 2;
|
|
@@ -2798,8 +2930,8 @@ async function boot(argv) {
|
|
|
2798
2930
|
if (isHomeDirectory(cwd, userHome)) {
|
|
2799
2931
|
writeErr(
|
|
2800
2932
|
`
|
|
2801
|
-
${
|
|
2802
|
-
${
|
|
2933
|
+
${color11.red(color11.bold("\u26A0 This is not a working directory."))}
|
|
2934
|
+
${color11.red("Please open wstack in a project folder.")}
|
|
2803
2935
|
|
|
2804
2936
|
`
|
|
2805
2937
|
);
|
|
@@ -2807,23 +2939,21 @@ async function boot(argv) {
|
|
|
2807
2939
|
return 1;
|
|
2808
2940
|
}
|
|
2809
2941
|
if (!flags["no-models-refresh"]) {
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
logger
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
logger.warn(`models.dev refresh failed (${msg}); using cached catalog`);
|
|
2816
|
-
}
|
|
2942
|
+
await startCatalog({
|
|
2943
|
+
registry: modelsRegistry,
|
|
2944
|
+
logger,
|
|
2945
|
+
shortLived: positional.length > 0 || typeof flags["prompt"] === "string"
|
|
2946
|
+
});
|
|
2817
2947
|
}
|
|
2818
2948
|
try {
|
|
2819
2949
|
await discoverAndMergeProviders({
|
|
2820
2950
|
config,
|
|
2821
2951
|
registry: modelsRegistry,
|
|
2822
|
-
cacheDir:
|
|
2952
|
+
cacheDir: path9.dirname(wpaths.modelsCache),
|
|
2823
2953
|
logger
|
|
2824
2954
|
});
|
|
2825
2955
|
} catch (err) {
|
|
2826
|
-
logger.debug(`provider auto-discovery skipped: ${
|
|
2956
|
+
logger.debug(`provider auto-discovery skipped: ${toErrorMessage5(err)}`);
|
|
2827
2957
|
}
|
|
2828
2958
|
const isSingleShot = positional.length > 0 || typeof flags["prompt"] === "string";
|
|
2829
2959
|
const isInteractiveTTY = isStdinTTY2() && !isSingleShot && !flags["webui"] && !flags["no-interactive"] && !flags["skip"];
|
|
@@ -2858,11 +2988,11 @@ async function boot(argv) {
|
|
|
2858
2988
|
if (isStdinTTY2() && !noInteractiveMode) {
|
|
2859
2989
|
let picked;
|
|
2860
2990
|
let skipPicker = false;
|
|
2861
|
-
if (
|
|
2991
|
+
if (isSetupProvider2(config.provider)) {
|
|
2862
2992
|
skipPicker = true;
|
|
2863
2993
|
renderer.write(
|
|
2864
2994
|
`
|
|
2865
|
-
${
|
|
2995
|
+
${color11.amber("\u25B6")} ${color11.bold("Setup mode")} ${color11.dim("\u2014 no model connected. Run")} ${color11.bold("/auth")} ${color11.dim("to connect one.")}
|
|
2866
2996
|
|
|
2867
2997
|
`
|
|
2868
2998
|
);
|
|
@@ -2889,7 +3019,7 @@ async function boot(argv) {
|
|
|
2889
3019
|
config = reloaded.config;
|
|
2890
3020
|
vault = reloaded.vault;
|
|
2891
3021
|
} catch (err) {
|
|
2892
|
-
writeErr(`Config error after setup: ${
|
|
3022
|
+
writeErr(`Config error after setup: ${toErrorMessage5(err)}
|
|
2893
3023
|
`);
|
|
2894
3024
|
await reader.close();
|
|
2895
3025
|
return 2;
|
|
@@ -2902,7 +3032,7 @@ async function boot(argv) {
|
|
|
2902
3032
|
const savedStatus = await validateSavedProviderModel(config, modelsRegistry);
|
|
2903
3033
|
renderer.write(
|
|
2904
3034
|
`
|
|
2905
|
-
${
|
|
3035
|
+
${color11.dim("Last settings:")} ${color11.bold(savedProvider)} / ${color11.bold(savedModel)}
|
|
2906
3036
|
`
|
|
2907
3037
|
);
|
|
2908
3038
|
if (!savedStatus.ok) {
|
|
@@ -2912,11 +3042,11 @@ async function boot(argv) {
|
|
|
2912
3042
|
);
|
|
2913
3043
|
} else {
|
|
2914
3044
|
const answer = (await reader.readLine(
|
|
2915
|
-
` ${
|
|
3045
|
+
` ${color11.amber("?")} Continue with these? ${color11.dim("[Y/n/q]")} ${color11.dim("(auto Y in 5s)")} `,
|
|
2916
3046
|
{ timeoutMs: 5e3, defaultAnswer: "y" }
|
|
2917
3047
|
)).trim().toLowerCase();
|
|
2918
3048
|
if (answer === "q") {
|
|
2919
|
-
renderer.write(
|
|
3049
|
+
renderer.write(color11.dim(" Goodbye!\n"));
|
|
2920
3050
|
await reader.close();
|
|
2921
3051
|
return 0;
|
|
2922
3052
|
}
|
|
@@ -2924,7 +3054,7 @@ async function boot(argv) {
|
|
|
2924
3054
|
skipPicker = true;
|
|
2925
3055
|
renderer.write(
|
|
2926
3056
|
`
|
|
2927
|
-
${
|
|
3057
|
+
${color11.green("\u25B6")} ${color11.bold(savedProvider)} / ${color11.bold(savedModel)}
|
|
2928
3058
|
|
|
2929
3059
|
`
|
|
2930
3060
|
);
|
|
@@ -2945,9 +3075,9 @@ async function boot(argv) {
|
|
|
2945
3075
|
if (!config.provider || !config.model) {
|
|
2946
3076
|
renderer.write(
|
|
2947
3077
|
`
|
|
2948
|
-
${
|
|
2949
|
-
${
|
|
2950
|
-
${
|
|
3078
|
+
${color11.dim("No provider selected.")}
|
|
3079
|
+
${color11.dim("Run")} ${color11.bold("wstack auth")} ${color11.dim("to add a key or sign in, or start with no model:")}
|
|
3080
|
+
${color11.bold(`wstack --provider ${SETUP_PROVIDER_ID} --model ${SETUP_MODEL_ID}`)}
|
|
2951
3081
|
|
|
2952
3082
|
`
|
|
2953
3083
|
);
|
|
@@ -3017,7 +3147,7 @@ To start the app with no model connected, pass --provider ${SETUP_PROVIDER_ID} -
|
|
|
3017
3147
|
}
|
|
3018
3148
|
if (promptMenu.persistError) {
|
|
3019
3149
|
renderer.writeWarning(
|
|
3020
|
-
`Could not save system prompt variant to config: ${
|
|
3150
|
+
`Could not save system prompt variant to config: ${toErrorMessage5(promptMenu.persistError)}
|
|
3021
3151
|
`
|
|
3022
3152
|
);
|
|
3023
3153
|
}
|
|
@@ -3069,8 +3199,8 @@ To start the app with no model connected, pass --provider ${SETUP_PROVIDER_ID} -
|
|
|
3069
3199
|
if (shouldPrintYoloNotice(lastChoices, yoloPinned, choices.yolo)) {
|
|
3070
3200
|
writeErr(
|
|
3071
3201
|
`
|
|
3072
|
-
${
|
|
3073
|
-
${
|
|
3202
|
+
${color11.yellow("YOLO is on")}: non-denied tool calls, including shell and file writes, run without confirmation.
|
|
3203
|
+
${color11.dim("Explicit deny rules still apply. Use")} --no-yolo ${color11.dim("or")} /yolo off ${color11.dim("to require prompts.")}
|
|
3074
3204
|
|
|
3075
3205
|
`
|
|
3076
3206
|
);
|
|
@@ -3121,64 +3251,13 @@ To start the app with no model connected, pass --provider ${SETUP_PROVIDER_ID} -
|
|
|
3121
3251
|
needsSetup: !noInteractiveMode ? false : !config.provider || !config.model
|
|
3122
3252
|
};
|
|
3123
3253
|
}
|
|
3124
|
-
async function checkGitInCwd(opts) {
|
|
3125
|
-
const { cwd, renderer, reader } = opts;
|
|
3126
|
-
const cwdGit = path7.join(cwd, ".git");
|
|
3127
|
-
let hasCwdGit = false;
|
|
3128
|
-
try {
|
|
3129
|
-
await fs6.access(cwdGit);
|
|
3130
|
-
hasCwdGit = true;
|
|
3131
|
-
} catch {
|
|
3132
|
-
}
|
|
3133
|
-
if (!hasCwdGit) {
|
|
3134
|
-
renderer.write(
|
|
3135
|
-
`
|
|
3136
|
-
${color10.amber("\u25CB")} This folder has no ${color10.bold(".git")} repository.
|
|
3137
|
-
`
|
|
3138
|
-
);
|
|
3139
|
-
const answer = (await reader.readLine(` ${color10.amber("?")} Initialize one here? ${color10.dim("[y/N]")} `)).trim().toLowerCase();
|
|
3140
|
-
if (answer === "y" || answer === "yes") {
|
|
3141
|
-
try {
|
|
3142
|
-
const { spawn: spawn2 } = await import("node:child_process");
|
|
3143
|
-
await new Promise((resolve2, reject) => {
|
|
3144
|
-
const child = spawn2("git", ["init"], {
|
|
3145
|
-
cwd,
|
|
3146
|
-
signal: AbortSignal.timeout(1e4),
|
|
3147
|
-
windowsHide: true
|
|
3148
|
-
});
|
|
3149
|
-
child.on("error", reject);
|
|
3150
|
-
child.on(
|
|
3151
|
-
"close",
|
|
3152
|
-
(code) => code === 0 ? resolve2() : reject(new Error(`git init failed with ${code}`))
|
|
3153
|
-
);
|
|
3154
|
-
});
|
|
3155
|
-
renderer.write(` ${color10.green("\u2713")} Git repository initialized
|
|
3156
|
-
`);
|
|
3157
|
-
hasCwdGit = true;
|
|
3158
|
-
} catch (err) {
|
|
3159
|
-
renderer.writeError(`git init failed: ${toErrorMessage4(err)}
|
|
3160
|
-
`);
|
|
3161
|
-
}
|
|
3162
|
-
}
|
|
3163
|
-
}
|
|
3164
|
-
const parentDir = path7.dirname(cwd);
|
|
3165
|
-
if (parentDir !== cwd) {
|
|
3166
|
-
try {
|
|
3167
|
-
await fs6.access(path7.join(parentDir, ".git"));
|
|
3168
|
-
renderer.write(
|
|
3169
|
-
` ${color10.dim("\u2139")} A ${color10.bold(".git")} repo exists in the parent directory: ${color10.dim(parentDir)}
|
|
3170
|
-
`
|
|
3171
|
-
);
|
|
3172
|
-
} catch {
|
|
3173
|
-
}
|
|
3174
|
-
}
|
|
3175
|
-
}
|
|
3176
3254
|
|
|
3177
3255
|
// src/cli-context.ts
|
|
3178
3256
|
async function initializeCli(argv) {
|
|
3179
3257
|
applyNodeEnvDefault();
|
|
3180
3258
|
applySessionShellDefault();
|
|
3181
3259
|
const earlyFlags = parseArgs(argv).flags;
|
|
3260
|
+
applyAsciiMode(earlyFlags);
|
|
3182
3261
|
const earlyExit = await handleHelpVersionShortCircuit(argv);
|
|
3183
3262
|
if (earlyExit !== null) return earlyExit;
|
|
3184
3263
|
const desktopExit = await handleDesktopShortCircuit(earlyFlags, argv);
|
|
@@ -3319,7 +3398,8 @@ async function initializeCli(argv) {
|
|
|
3319
3398
|
logger,
|
|
3320
3399
|
reader,
|
|
3321
3400
|
renderer,
|
|
3322
|
-
modelsRegistry
|
|
3401
|
+
modelsRegistry,
|
|
3402
|
+
launchAllowedTools: resolveLaunchAllowedTools(ctx.flags)
|
|
3323
3403
|
});
|
|
3324
3404
|
const configStore = container.resolve(TOKENS3.ConfigStore);
|
|
3325
3405
|
return {
|
|
@@ -3335,4 +3415,4 @@ async function initializeCli(argv) {
|
|
|
3335
3415
|
export {
|
|
3336
3416
|
initializeCli
|
|
3337
3417
|
};
|
|
3338
|
-
//# sourceMappingURL=cli-context-
|
|
3418
|
+
//# sourceMappingURL=cli-context-UVGAN3NO.js.map
|