@wrongstack/cli 1.0.26 → 1.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{acp-LI665LO2.js → acp-M4565YUW.js} +30 -17
- package/dist/boot/dispatch-singleshot.d.ts +8 -0
- package/dist/boot/dispatch-webui.d.ts +2 -0
- package/dist/boot/goal-tui-default.d.ts +10 -0
- package/dist/{chunk-OAVBM55Q.js → chunk-ENRYW73H.js} +525 -379
- package/dist/chunk-HDMFKTT3.js +157 -0
- package/dist/{chunk-WQV2NP57.js → chunk-HFZH2XJN.js} +2 -2
- package/dist/{chunk-BEHGRNOQ.js → chunk-N57IU5FG.js} +9 -9
- package/dist/{chunk-2EBVTYJR.js → chunk-NRXWOMK7.js} +17 -3
- package/dist/{chunk-5SEYGOCH.js → chunk-RDGGWMTI.js} +2 -2
- package/dist/{chunk-KJS5543T.js → chunk-RGFWGUAB.js} +26 -14
- package/dist/{chunk-S4FFHDJG.js → chunk-SDJCLEK6.js} +6 -2
- package/dist/{cli-context-UVGAN3NO.js → cli-context-C7RBSWHF.js} +33 -6
- package/dist/{cli-main-TN3KZ2P6.js → cli-main-TQTH73ZK.js} +304 -345
- package/dist/{execution-7QIP6GRY.js → execution-3STBD2U7.js} +87 -33
- package/dist/execution-chimera-review.d.ts +18 -1
- package/dist/{hq-GLZ7QESM.js → hq-44F4OQH2.js} +5 -4
- package/dist/hq-fleet-control.d.ts +36 -0
- package/dist/hq-live-status.d.ts +22 -0
- package/dist/hq-publisher.d.ts +18 -0
- package/dist/hq-server/routes/command-handlers.d.ts +12 -1
- package/dist/hq-server/routes/data-handlers.d.ts +1 -1
- package/dist/hq-server/socket-credentials.d.ts +63 -0
- package/dist/hq-server/upgrade-handler.d.ts +2 -0
- package/dist/hq-server/ws.d.ts +24 -0
- package/dist/{hq-server-YTKDVQPY.js → hq-server-UIB24LU6.js} +2 -2
- package/dist/{import-claude-code-32PCSIQI.js → import-claude-code-AYG24RG2.js} +36 -4
- package/dist/index.js +3 -3
- package/dist/live-settings-input.d.ts +1 -0
- package/dist/{mailbox-serve-NW5VZG7R.js → mailbox-serve-GNGXEQ2R.js} +2 -2
- package/dist/{modeldiag-36VODVIH.js → modeldiag-W7XAE625.js} +2 -2
- package/dist/{remote-O5WXHLWV.js → remote-GB5VXCCT.js} +38 -23
- package/dist/{sessions-config-SXTTLNXA.js → sessions-config-XHLXJ5C3.js} +75 -6
- package/dist/{short-circuit-flags-74Y5N6CF.js → short-circuit-flags-5TNTJPQR.js} +2 -2
- package/dist/slash-commands/theme.d.ts +15 -1
- package/dist/subcommands/handlers/import-claude-code.d.ts +10 -0
- package/dist/subcommands/handlers/sessions-fleet.d.ts +0 -12
- package/dist/{subcommands-Q6ORSB2E.js → subcommands-BHQYLDSD.js} +2 -2
- package/dist/{webui-server-YTHLRFD2.js → webui-server-GCXIO3JY.js} +37 -30
- package/dist/webui-server-options.d.ts +10 -0
- package/dist/wiring/command-host-state.d.ts +2 -0
- package/dist/wiring/hq-telemetry.d.ts +12 -0
- package/package.json +29 -28
- package/dist/chunk-OWNC7LMD.js +0 -78
|
@@ -17,6 +17,25 @@ import { mcpEnvPlaceholders } from "@wrongstack/mcp";
|
|
|
17
17
|
function isRecord(value) {
|
|
18
18
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19
19
|
}
|
|
20
|
+
var REPOSITORY_STRIPPED_MCP_FIELDS = [
|
|
21
|
+
"permission",
|
|
22
|
+
"bearerTokenEnv",
|
|
23
|
+
"passthroughEnv",
|
|
24
|
+
"allowPrivateNetworks"
|
|
25
|
+
];
|
|
26
|
+
function envReads(config) {
|
|
27
|
+
const reads = new Set(mcpEnvPlaceholders(config));
|
|
28
|
+
if (config.bearerTokenEnv) reads.add(config.bearerTokenEnv);
|
|
29
|
+
for (const name of config.passthroughEnv ?? []) reads.add(name);
|
|
30
|
+
return [...reads];
|
|
31
|
+
}
|
|
32
|
+
function describeTarget(config) {
|
|
33
|
+
if (typeof config.command === "string") {
|
|
34
|
+
return `runs: ${[config.command, ...config.args ?? []].join(" ")}`;
|
|
35
|
+
}
|
|
36
|
+
if (typeof config.url === "string") return `connects to: ${config.url}`;
|
|
37
|
+
return void 0;
|
|
38
|
+
}
|
|
20
39
|
function samePath(a, b) {
|
|
21
40
|
const norm = (p) => {
|
|
22
41
|
const resolved = path.resolve(p).replace(/[\\/]+$/, "");
|
|
@@ -58,10 +77,22 @@ function planClaudeCodeImport(opts) {
|
|
|
58
77
|
const exists2 = Object.hasOwn(opts.existingServers, name);
|
|
59
78
|
const repository = source === "repository";
|
|
60
79
|
const enabled = !repository || opts.enableProjectServers;
|
|
61
|
-
const
|
|
80
|
+
const stripped = [];
|
|
81
|
+
if (repository) {
|
|
82
|
+
for (const field of REPOSITORY_STRIPPED_MCP_FIELDS) {
|
|
83
|
+
if (config[field] === void 0) continue;
|
|
84
|
+
delete config[field];
|
|
85
|
+
stripped.push(field);
|
|
86
|
+
}
|
|
87
|
+
config.origin = "repository";
|
|
88
|
+
}
|
|
89
|
+
const reads = envReads(config);
|
|
90
|
+
const target = describeTarget(config);
|
|
62
91
|
const notes2 = [
|
|
92
|
+
target,
|
|
63
93
|
repository && !enabled ? "from the repository \u2014 imported disabled; review, then `/mcp enable`" : void 0,
|
|
64
|
-
reads.length > 0 ? `reads environment: ${reads.join(", ")}` : void 0
|
|
94
|
+
reads.length > 0 ? `reads environment: ${reads.join(", ")}` : void 0,
|
|
95
|
+
stripped.length > 0 ? `not imported from the repository: ${stripped.join(", ")} (set them yourself after review)` : void 0
|
|
65
96
|
].filter((note) => note !== void 0);
|
|
66
97
|
mcp.push({
|
|
67
98
|
name,
|
|
@@ -77,8 +108,8 @@ function planClaudeCodeImport(opts) {
|
|
|
77
108
|
projectEntry(sources.userState, opts.projectRoot)?.["mcpServers"],
|
|
78
109
|
"claude-project-local"
|
|
79
110
|
);
|
|
80
|
-
collect(sources.projectMcp?.["mcpServers"] ?? sources.projectMcp, "repository");
|
|
81
111
|
collect(sources.userState?.["mcpServers"], "claude-user");
|
|
112
|
+
collect(sources.projectMcp?.["mcpServers"] ?? sources.projectMcp, "repository");
|
|
82
113
|
const notes = [];
|
|
83
114
|
if (sources.skillDirs.length > 0) {
|
|
84
115
|
notes.push(
|
|
@@ -229,8 +260,9 @@ Wrote ${writes.length} server(s) to ${configPath}.`);
|
|
|
229
260
|
return 0;
|
|
230
261
|
};
|
|
231
262
|
export {
|
|
263
|
+
REPOSITORY_STRIPPED_MCP_FIELDS,
|
|
232
264
|
importClaudeCodeCmd,
|
|
233
265
|
planClaudeCodeImport,
|
|
234
266
|
readClaudeCodeSources
|
|
235
267
|
};
|
|
236
|
-
//# sourceMappingURL=import-claude-code-
|
|
268
|
+
//# sourceMappingURL=import-claude-code-AYG24RG2.js.map
|
package/dist/index.js
CHANGED
|
@@ -20,14 +20,14 @@ async function main(argv) {
|
|
|
20
20
|
applyAsciiMode(earlyFlags);
|
|
21
21
|
}
|
|
22
22
|
if (earlyFlags["help"] === true || earlyFlags["version"] === true) {
|
|
23
|
-
const { handleHelpVersionShortCircuit } = await import("./short-circuit-flags-
|
|
23
|
+
const { handleHelpVersionShortCircuit } = await import("./short-circuit-flags-5TNTJPQR.js");
|
|
24
24
|
const earlyExit = await handleHelpVersionShortCircuit(argv);
|
|
25
25
|
if (earlyExit !== null) return earlyExit;
|
|
26
26
|
}
|
|
27
|
-
const { initializeCli } = await import("./cli-context-
|
|
27
|
+
const { initializeCli } = await import("./cli-context-C7RBSWHF.js");
|
|
28
28
|
const cliCtx = await initializeCli(argv);
|
|
29
29
|
if (typeof cliCtx === "number") return cliCtx;
|
|
30
|
-
const { runInteractive } = await import("./cli-main-
|
|
30
|
+
const { runInteractive } = await import("./cli-main-TQTH73ZK.js");
|
|
31
31
|
return runInteractive(cliCtx);
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -19,6 +19,7 @@ export interface LiveSettingsInput {
|
|
|
19
19
|
featureMemory?: boolean | undefined;
|
|
20
20
|
featureSkills?: boolean | undefined;
|
|
21
21
|
featureModelsRegistry?: boolean | undefined;
|
|
22
|
+
featureToolCoach?: boolean | undefined;
|
|
22
23
|
featureTokenSaving?: TokenSavingTier | undefined;
|
|
23
24
|
allowOutsideProjectRoot?: boolean | undefined;
|
|
24
25
|
contextAutoCompact?: boolean | undefined;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
startCliHqConnection
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RGFWGUAB.js";
|
|
4
4
|
import "./chunk-F5DCFAKI.js";
|
|
5
5
|
|
|
6
6
|
// src/subcommands/handlers/mailbox-serve.ts
|
|
@@ -361,4 +361,4 @@ function printHelp(deps) {
|
|
|
361
361
|
export {
|
|
362
362
|
mailboxServeCmd
|
|
363
363
|
};
|
|
364
|
-
//# sourceMappingURL=mailbox-serve-
|
|
364
|
+
//# sourceMappingURL=mailbox-serve-GNGXEQ2R.js.map
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
} from "./chunk-BBHWW6LR.js";
|
|
21
21
|
import {
|
|
22
22
|
resolveRawProviderConnection
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-SDJCLEK6.js";
|
|
24
24
|
import {
|
|
25
25
|
mutateConfigProviders
|
|
26
26
|
} from "./chunk-LUMETJFO.js";
|
|
@@ -825,4 +825,4 @@ var modeldiagCmd = async (args, deps) => {
|
|
|
825
825
|
export {
|
|
826
826
|
modeldiagCmd
|
|
827
827
|
};
|
|
828
|
-
//# sourceMappingURL=modeldiag-
|
|
828
|
+
//# sourceMappingURL=modeldiag-W7XAE625.js.map
|
|
@@ -28,6 +28,13 @@ import { buildChildEnv, toErrorMessage } from "@wrongstack/core/utils";
|
|
|
28
28
|
|
|
29
29
|
// src/remote/remote-target.ts
|
|
30
30
|
function parseRemoteTarget(input) {
|
|
31
|
+
const target = parseRemoteTargetText(input);
|
|
32
|
+
if (target.destination.startsWith("-")) {
|
|
33
|
+
throw new Error(`A remote host cannot start with "-" (got ${target.destination})`);
|
|
34
|
+
}
|
|
35
|
+
return target;
|
|
36
|
+
}
|
|
37
|
+
function parseRemoteTargetText(input) {
|
|
31
38
|
const text = input.trim();
|
|
32
39
|
if (text.startsWith("ssh://")) {
|
|
33
40
|
let url;
|
|
@@ -73,22 +80,30 @@ function buildTargetFor(os, arch, musl) {
|
|
|
73
80
|
throw new Error(`Remote machines running ${os} are not supported (Linux and macOS are).`);
|
|
74
81
|
}
|
|
75
82
|
var REMOTE_BIN_DIR = '"$HOME"/.wrongstack/remote';
|
|
83
|
+
function stateScript(path3) {
|
|
84
|
+
return `dir=${shPath(path3)}
|
|
85
|
+
abs=$(cd "$dir" 2>/dev/null && pwd -P) || abs=
|
|
86
|
+
key=$(printf '%s' "$abs" | cksum | tr ' ' '-')
|
|
87
|
+
state_dir=${REMOTE_BIN_DIR}/servers
|
|
88
|
+
state="$state_dir/$key.json"
|
|
89
|
+
token_file="$state_dir/$key.token"
|
|
90
|
+
log="$state_dir/$key.log"`;
|
|
91
|
+
}
|
|
76
92
|
function probeScript(path3) {
|
|
77
93
|
return `set -u
|
|
78
94
|
printf 'os=%s\\n' "$(uname -s 2>/dev/null)"
|
|
79
95
|
printf 'arch=%s\\n' "$(uname -m 2>/dev/null)"
|
|
80
96
|
if ls /lib/ld-musl-* >/dev/null 2>&1; then echo musl=1; else echo musl=0; fi
|
|
81
|
-
|
|
97
|
+
${stateScript(path3)}
|
|
82
98
|
if [ -d "$dir" ]; then echo path=1; else echo path=0; fi
|
|
83
99
|
for f in ${REMOTE_BIN_DIR}/wstack-*; do
|
|
84
100
|
[ -x "$f" ] && printf 'version=%s\\n' "\${f##*/wstack-}"
|
|
85
101
|
done
|
|
86
|
-
|
|
87
|
-
if [ -f "$state" ] && [ -f "$dir/.wrongstack/remote-webui.token" ]; then
|
|
102
|
+
if [ -n "$abs" ] && [ -f "$state" ] && [ -f "$token_file" ]; then
|
|
88
103
|
pid=$(sed -n 's/.*"pid":\\([0-9]*\\).*/\\1/p' "$state")
|
|
89
104
|
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
|
|
90
105
|
printf 'server=%s\\n' "$(tr -d '\\n' < "$state")"
|
|
91
|
-
printf 'token=%s\\n' "$(cat "$
|
|
106
|
+
printf 'token=%s\\n' "$(cat "$token_file")"
|
|
92
107
|
fi
|
|
93
108
|
fi
|
|
94
109
|
`;
|
|
@@ -141,12 +156,12 @@ var NO_PROVIDER = ["No provider or model configured", "Saved provider/model is n
|
|
|
141
156
|
function startScript(options) {
|
|
142
157
|
const bin = remoteBinaryPath(options.version);
|
|
143
158
|
return `set -u
|
|
144
|
-
dir=${shPath(options.path)}
|
|
145
|
-
cd "$dir" || { echo error=path; exit 3; }
|
|
146
159
|
umask 077
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
160
|
+
${stateScript(options.path)}
|
|
161
|
+
cd "$dir" || { echo error=path; exit 3; }
|
|
162
|
+
mkdir -p "$state_dir"
|
|
163
|
+
chmod 700 "$state_dir"
|
|
164
|
+
printf '%s' ${shQuote(options.token)} > "$token_file"
|
|
150
165
|
export WEBUI_TOKEN=${shQuote(options.token)}
|
|
151
166
|
launch() {
|
|
152
167
|
: > "$log"
|
|
@@ -171,21 +186,21 @@ await_port() {
|
|
|
171
186
|
}
|
|
172
187
|
launch
|
|
173
188
|
await_port
|
|
174
|
-
|
|
175
|
-
if [ "$
|
|
189
|
+
status=$?
|
|
190
|
+
if [ "$status" -eq 1 ] && grep -q ${NO_PROVIDER.map((line) => `-e ${shQuote(line)}`).join(" ")} "$log"; then
|
|
176
191
|
echo setup=1
|
|
177
192
|
launch --provider wrongstack-setup --model no-api-key
|
|
178
193
|
await_port
|
|
179
|
-
|
|
194
|
+
status=$?
|
|
180
195
|
fi
|
|
181
|
-
if [ "$
|
|
182
|
-
printf '{"pid":%s,"port":%s,"version":"%s"}\\n' "$pid" "$port" ${shQuote(options.version)} >
|
|
196
|
+
if [ "$status" -eq 0 ]; then
|
|
197
|
+
printf '{"pid":%s,"port":%s,"version":"%s"}\\n' "$pid" "$port" ${shQuote(options.version)} > "$state"
|
|
183
198
|
echo "port=$port"
|
|
184
199
|
echo "pid=$pid"
|
|
185
200
|
exit 0
|
|
186
201
|
fi
|
|
187
|
-
rm -f
|
|
188
|
-
if [ "$
|
|
202
|
+
rm -f "$token_file"
|
|
203
|
+
if [ "$status" -eq 1 ]; then
|
|
189
204
|
echo error=exited
|
|
190
205
|
tail -n 30 "$log" | sed 's/^/log=/'
|
|
191
206
|
exit 4
|
|
@@ -197,12 +212,11 @@ exit 5
|
|
|
197
212
|
}
|
|
198
213
|
function stopScript(path3) {
|
|
199
214
|
return `set -u
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
[ -f "$state" ] || exit 0
|
|
215
|
+
${stateScript(path3)}
|
|
216
|
+
[ -n "$abs" ] && [ -f "$state" ] || exit 0
|
|
203
217
|
pid=$(sed -n 's/.*"pid":\\([0-9]*\\).*/\\1/p' "$state")
|
|
204
218
|
[ -n "$pid" ] && kill "$pid" 2>/dev/null
|
|
205
|
-
rm -f "$state" "$
|
|
219
|
+
rm -f "$state" "$token_file"
|
|
206
220
|
echo stopped=1
|
|
207
221
|
`;
|
|
208
222
|
}
|
|
@@ -333,7 +347,7 @@ async function runRemoteSession(opts) {
|
|
|
333
347
|
await exited(tunnel);
|
|
334
348
|
opts.signal.removeEventListener("abort", stopTunnel);
|
|
335
349
|
throw new Error(
|
|
336
|
-
`The WebUI on ${opts.target.destination} did not answer through the SSH tunnel. Check that its sshd allows port forwarding (AllowTcpForwarding) and see
|
|
350
|
+
`The WebUI on ${opts.target.destination} did not answer through the SSH tunnel. Check that its sshd allows port forwarding (AllowTcpForwarding) and see the host log under ~/.wrongstack/remote/servers/ there.`
|
|
337
351
|
);
|
|
338
352
|
}
|
|
339
353
|
}
|
|
@@ -406,7 +420,7 @@ function sshCommandLine(target, options) {
|
|
|
406
420
|
function systemSsh(target, options) {
|
|
407
421
|
const base = sshCommandLine(target, options);
|
|
408
422
|
const run = (remoteCommand, input) => new Promise((resolve2) => {
|
|
409
|
-
const child = spawn("ssh", [...base, target.destination, remoteCommand], {
|
|
423
|
+
const child = spawn("ssh", [...base, "--", target.destination, remoteCommand], {
|
|
410
424
|
stdio: ["pipe", "pipe", "inherit"],
|
|
411
425
|
env: { ...buildChildEnv(), ...sshAgentEnv() },
|
|
412
426
|
windowsHide: true
|
|
@@ -431,6 +445,7 @@ function systemSsh(target, options) {
|
|
|
431
445
|
"ExitOnForwardFailure=yes",
|
|
432
446
|
"-L",
|
|
433
447
|
`127.0.0.1:${localPort}:127.0.0.1:${remotePort}`,
|
|
448
|
+
"--",
|
|
434
449
|
target.destination
|
|
435
450
|
],
|
|
436
451
|
{
|
|
@@ -558,4 +573,4 @@ export {
|
|
|
558
573
|
remoteCmd,
|
|
559
574
|
runRemoteCommand
|
|
560
575
|
};
|
|
561
|
-
//# sourceMappingURL=remote-
|
|
576
|
+
//# sourceMappingURL=remote-GB5VXCCT.js.map
|
|
@@ -33,6 +33,40 @@ function redactKeys(obj) {
|
|
|
33
33
|
import * as fsp from "node:fs/promises";
|
|
34
34
|
import * as path from "node:path";
|
|
35
35
|
import { color } from "@wrongstack/core/utils";
|
|
36
|
+
var STORE_SIDECAR_JSONL_NAMES = /* @__PURE__ */ new Set(["_index.jsonl", "_mailbox.jsonl"]);
|
|
37
|
+
var SESSION_SIDECAR_JSONL_SUFFIXES = [".replay.jsonl", ".audit.jsonl", ".annotations.jsonl"];
|
|
38
|
+
function isSubagentTranscriptFile(name) {
|
|
39
|
+
const lower = name.toLowerCase();
|
|
40
|
+
if (!lower.endsWith(".jsonl")) return false;
|
|
41
|
+
if (STORE_SIDECAR_JSONL_NAMES.has(lower)) return false;
|
|
42
|
+
return !SESSION_SIDECAR_JSONL_SUFFIXES.some((suffix) => lower.endsWith(suffix));
|
|
43
|
+
}
|
|
44
|
+
async function collectSubagentTranscripts(subagentsDir) {
|
|
45
|
+
let entries;
|
|
46
|
+
try {
|
|
47
|
+
entries = await fsp.readdir(subagentsDir, { withFileTypes: true });
|
|
48
|
+
} catch {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
const out = [];
|
|
52
|
+
for (const entry of entries) {
|
|
53
|
+
if (entry.isFile()) {
|
|
54
|
+
if (isSubagentTranscriptFile(entry.name)) out.push(entry.name);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (!entry.isDirectory() || entry.name === "transcripts" || entry.name === "shared") continue;
|
|
58
|
+
let nested;
|
|
59
|
+
try {
|
|
60
|
+
nested = await fsp.readdir(path.join(subagentsDir, entry.name));
|
|
61
|
+
} catch {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
for (const name of nested) {
|
|
65
|
+
if (isSubagentTranscriptFile(name)) out.push(`${entry.name}/${name}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
36
70
|
var sessionsFleetCmd = async (args, deps) => {
|
|
37
71
|
const runId = args.find((a) => !a.startsWith("-"));
|
|
38
72
|
if (runId) {
|
|
@@ -40,10 +74,46 @@ var sessionsFleetCmd = async (args, deps) => {
|
|
|
40
74
|
}
|
|
41
75
|
return listFleetRuns(deps);
|
|
42
76
|
};
|
|
77
|
+
async function hasFleetRunArtifacts(dir) {
|
|
78
|
+
const markers = await Promise.all(
|
|
79
|
+
["fleet.json", "checkpoint.json", "subagents"].map(
|
|
80
|
+
(name) => fsp.access(path.join(dir, name)).then(
|
|
81
|
+
() => true,
|
|
82
|
+
() => false
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
);
|
|
86
|
+
return markers.some((found) => found);
|
|
87
|
+
}
|
|
88
|
+
async function discoverFleetRunIds(projectSessions) {
|
|
89
|
+
const entries = await fsp.readdir(projectSessions, { withFileTypes: true });
|
|
90
|
+
const ids = [];
|
|
91
|
+
for (const entry of entries) {
|
|
92
|
+
if (!entry.isDirectory()) continue;
|
|
93
|
+
const dir = path.join(projectSessions, entry.name);
|
|
94
|
+
if (await hasFleetRunArtifacts(dir)) {
|
|
95
|
+
ids.push(entry.name);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
let children;
|
|
99
|
+
try {
|
|
100
|
+
children = await fsp.readdir(dir, { withFileTypes: true });
|
|
101
|
+
} catch {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
for (const child of children) {
|
|
105
|
+
if (!child.isDirectory()) continue;
|
|
106
|
+
if (await hasFleetRunArtifacts(path.join(dir, child.name))) {
|
|
107
|
+
ids.push(`${entry.name}/${child.name}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return ids;
|
|
112
|
+
}
|
|
43
113
|
async function listFleetRuns(deps) {
|
|
44
114
|
let entries = [];
|
|
45
115
|
try {
|
|
46
|
-
entries = await
|
|
116
|
+
entries = await discoverFleetRunIds(deps.paths.projectSessions);
|
|
47
117
|
} catch {
|
|
48
118
|
deps.renderer.writeError(`Cannot read projectSessions: ${deps.paths.projectSessions}
|
|
49
119
|
`);
|
|
@@ -69,8 +139,8 @@ async function listFleetRuns(deps) {
|
|
|
69
139
|
() => true,
|
|
70
140
|
() => false
|
|
71
141
|
),
|
|
72
|
-
|
|
73
|
-
(files) => files.
|
|
142
|
+
collectSubagentTranscripts(path.join(runDir, "subagents")).then(
|
|
143
|
+
(files) => files.length,
|
|
74
144
|
() => 0
|
|
75
145
|
)
|
|
76
146
|
]);
|
|
@@ -189,8 +259,7 @@ Fleet Run: ${runId}
|
|
|
189
259
|
const subagentsDir = path.join(runDir, "subagents");
|
|
190
260
|
let subagentFiles = [];
|
|
191
261
|
try {
|
|
192
|
-
subagentFiles = await
|
|
193
|
-
subagentFiles = subagentFiles.filter((f) => f.endsWith(".jsonl"));
|
|
262
|
+
subagentFiles = await collectSubagentTranscripts(subagentsDir);
|
|
194
263
|
} catch {
|
|
195
264
|
}
|
|
196
265
|
if (subagentFiles.length > 0) {
|
|
@@ -456,4 +525,4 @@ export {
|
|
|
456
525
|
configCmd,
|
|
457
526
|
sessionsCmd
|
|
458
527
|
};
|
|
459
|
-
//# sourceMappingURL=sessions-config-
|
|
528
|
+
//# sourceMappingURL=sessions-config-XHLXJ5C3.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handleHelpVersionShortCircuit
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-HFZH2XJN.js";
|
|
4
4
|
import "./chunk-5JYDKG5B.js";
|
|
5
5
|
import "./chunk-F5DCFAKI.js";
|
|
6
6
|
import "./chunk-Q4INH2DG.js";
|
|
7
7
|
export {
|
|
8
8
|
handleHelpVersionShortCircuit
|
|
9
9
|
};
|
|
10
|
-
//# sourceMappingURL=short-circuit-flags-
|
|
10
|
+
//# sourceMappingURL=short-circuit-flags-5TNTJPQR.js.map
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
import type { InputReader, SlashCommand } from '@wrongstack/core/types';
|
|
1
|
+
import type { InputReader, SlashCommand, ThemePresetId } from '@wrongstack/core/types';
|
|
2
2
|
import type { SlashCommandContext } from './command-context.js';
|
|
3
|
+
interface ThemeOption {
|
|
4
|
+
id: ThemePresetId;
|
|
5
|
+
name: string;
|
|
6
|
+
desc: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The CLI's picker rows, exported for the TUI↔CLI agreement test
|
|
10
|
+
* (`packages/cli/tests/theme-metadata-agreement.test.ts`). The TUI derives its
|
|
11
|
+
* own rows from the same `THEME_PRESET_META` record, so this export is the
|
|
12
|
+
* second side of that comparison — it must stay in step with `THEME_OPTIONS`
|
|
13
|
+
* above.
|
|
14
|
+
*/
|
|
15
|
+
export declare const cliThemePickerOptions: readonly ThemeOption[];
|
|
3
16
|
/**
|
|
4
17
|
* Windowed slice of the theme list for the raw-terminal picker — mirrors the
|
|
5
18
|
* math in the TUI's `useWindowedPicker` (same centering + marker rules) so
|
|
@@ -35,4 +48,5 @@ export declare function truncateDesc(desc: string, columns: number, active: bool
|
|
|
35
48
|
export declare function buildThemeCommand(opts: SlashCommandContext & {
|
|
36
49
|
inputReader?: InputReader | undefined;
|
|
37
50
|
}): SlashCommand;
|
|
51
|
+
export {};
|
|
38
52
|
//# sourceMappingURL=theme.d.ts.map
|
|
@@ -28,6 +28,16 @@ export interface ClaudeCodeSources {
|
|
|
28
28
|
/** Skill directories that exist. */
|
|
29
29
|
skillDirs: string[];
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Fields a repository entry may not carry into the user's profile. Each one
|
|
33
|
+
* widens what the server gets on enable beyond "run this command / reach this
|
|
34
|
+
* URL": `permission` pre-approves every tool it exposes, `bearerTokenEnv` and
|
|
35
|
+
* `passthroughEnv` send the named environment variables to it, and
|
|
36
|
+
* `allowPrivateNetworks` lifts the internal-network guard. The repository
|
|
37
|
+
* chooses the command and URL, so it must not also choose those
|
|
38
|
+
* (WS-2026-09-26-05). The user can still set them after reviewing.
|
|
39
|
+
*/
|
|
40
|
+
export declare const REPOSITORY_STRIPPED_MCP_FIELDS: readonly ['permission', 'bearerTokenEnv', 'passthroughEnv', 'allowPrivateNetworks'];
|
|
31
41
|
/** Decide what an import would do. Pure: no reads, no writes. */
|
|
32
42
|
export declare function planClaudeCodeImport(opts: {
|
|
33
43
|
sources: ClaudeCodeSources;
|
|
@@ -1,15 +1,3 @@
|
|
|
1
1
|
import type { SubcommandHandler } from '../contracts.js';
|
|
2
|
-
/**
|
|
3
|
-
* `wrongstack sessions fleet [runId]`
|
|
4
|
-
*
|
|
5
|
-
* Lists fleet run artifacts under `projectSessions/<runId>/`.
|
|
6
|
-
* When runId is omitted, lists all fleet runs discovered under projectSessions.
|
|
7
|
-
*
|
|
8
|
-
* Artifacts shown:
|
|
9
|
-
* - fleet.json (manifest)
|
|
10
|
-
* - checkpoint.json (state snapshot, if present)
|
|
11
|
-
* - shared/ (scratchpad directory)
|
|
12
|
-
* - subagents/ (per-subagent JSONL transcripts)
|
|
13
|
-
*/
|
|
14
2
|
export declare const sessionsFleetCmd: SubcommandHandler;
|
|
15
3
|
//# sourceMappingURL=sessions-fleet.d.ts.map
|
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
createHqCommandDispatcher,
|
|
12
12
|
createProjectKanbanAssignHandler,
|
|
13
13
|
createProjectKanbanTransitionHandler
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-NRXWOMK7.js";
|
|
15
15
|
import {
|
|
16
16
|
startCliHqConnection
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-RGFWGUAB.js";
|
|
18
18
|
import {
|
|
19
19
|
CLI_VERSION
|
|
20
20
|
} from "./chunk-F5DCFAKI.js";
|
|
@@ -427,7 +427,10 @@ function createWebuiClientRegistration(deps) {
|
|
|
427
427
|
...deps.getSessionWriter ? { getSessionWriter: deps.getSessionWriter } : {},
|
|
428
428
|
startHqConnection: (options) => startCliHqConnection({
|
|
429
429
|
...options,
|
|
430
|
-
capabilities: options.capabilities
|
|
430
|
+
capabilities: options.capabilities,
|
|
431
|
+
// Embedded in the CLI host, whose own HQ connection already syncs
|
|
432
|
+
// this project's Kanban boards; a second sync is a second writer.
|
|
433
|
+
ownKanbanSync: false
|
|
431
434
|
}),
|
|
432
435
|
...control ? {
|
|
433
436
|
createCommandHandler: (mailbox, approvals) => createHqCommandDispatcher({
|
|
@@ -437,6 +440,9 @@ function createWebuiClientRegistration(deps) {
|
|
|
437
440
|
// Same registry the approval bridge publishes from, so every
|
|
438
441
|
// prompt HQ shows is one this handler can actually answer.
|
|
439
442
|
resolveApproval: (toolUseId, decision, sessionId) => approvals.resolve(toolUseId, decision, sessionId),
|
|
443
|
+
// Same registry again: it publishes `user_input.requested`, so
|
|
444
|
+
// it has to be the one that answers `answer-input`.
|
|
445
|
+
resolveUserInput: (requestId, response, sessionId) => approvals.resolveUserInput?.(requestId, response, sessionId) ?? false,
|
|
440
446
|
...deps.projectRoot ? {
|
|
441
447
|
kanbanTransition: createProjectKanbanTransitionHandler(deps.projectRoot),
|
|
442
448
|
kanbanAssign: createProjectKanbanAssignHandler(deps.projectRoot)
|
|
@@ -462,6 +468,20 @@ function createWebuiClientRegistration(deps) {
|
|
|
462
468
|
|
|
463
469
|
// src/webui-client-observability.ts
|
|
464
470
|
function createEmbeddedClientRegistration(opts, clients, abortControllers, getSessionAgents) {
|
|
471
|
+
const interruptSession = (sessionId) => {
|
|
472
|
+
const leaderId = sessionId ?? opts.session.id;
|
|
473
|
+
const controller = abortControllers.get(leaderId);
|
|
474
|
+
if (!controller) return false;
|
|
475
|
+
controller.abort();
|
|
476
|
+
try {
|
|
477
|
+
void Promise.resolve(opts.stopSessionFleet?.(leaderId)).catch(() => void 0);
|
|
478
|
+
} catch {
|
|
479
|
+
}
|
|
480
|
+
return true;
|
|
481
|
+
};
|
|
482
|
+
if (opts.interruptController) {
|
|
483
|
+
opts.interruptController.abortLeader = () => interruptSession(opts.agent.ctx.session?.id ?? opts.session.id);
|
|
484
|
+
}
|
|
465
485
|
return createWebuiClientRegistration({
|
|
466
486
|
projectRoot: opts.projectRoot,
|
|
467
487
|
appConfig: opts.appConfig,
|
|
@@ -478,36 +498,23 @@ function createEmbeddedClientRegistration(opts, clients, abortControllers, getSe
|
|
|
478
498
|
}
|
|
479
499
|
return [...ids];
|
|
480
500
|
},
|
|
481
|
-
// `cli-main` already runs a tracker and a bridge for the
|
|
482
|
-
//
|
|
483
|
-
// same agent list.
|
|
484
|
-
|
|
501
|
+
// `cli-main` already runs a tracker and a bridge for the root
|
|
502
|
+
// conversation; announcing it here too would put two trackers on one bus
|
|
503
|
+
// flushing the same agent list. Compared against the LIVE root writer:
|
|
504
|
+
// the CLI host's telemetry follows `ctx.session`, so once the root moves
|
|
505
|
+
// (session.new / resume) the old boot id is an ordinary tab this client
|
|
506
|
+
// must publish, and the new root id must not be published twice.
|
|
507
|
+
isSessionOwnedElsewhere: (sessionId) => sessionId === (opts.agent.ctx.session?.id ?? opts.session.id),
|
|
485
508
|
// The tab's own journal, so HQ takes its turns from the write path
|
|
486
509
|
// instead of tailing the file.
|
|
487
510
|
getSessionWriter: (sessionId) => getSessionAgents()?.peek(sessionId)?.ctx.session,
|
|
488
511
|
hqControl: {
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
// clearing early makes `isRunActive` lie to every tab still running.
|
|
496
|
-
// Every open tab is its own session with its own abort controller, so
|
|
497
|
-
// the command's session is the one that gets stopped. Falling back to
|
|
498
|
-
// the boot session keeps a dashboard that sends no session — every one
|
|
499
|
-
// before this existed — behaving exactly as before.
|
|
500
|
-
interruptLeader: (sessionId) => {
|
|
501
|
-
const leaderId = sessionId ?? opts.session.id;
|
|
502
|
-
const controller = abortControllers.get(leaderId);
|
|
503
|
-
if (!controller) return false;
|
|
504
|
-
controller.abort();
|
|
505
|
-
try {
|
|
506
|
-
void Promise.resolve(opts.stopSessionFleet?.(leaderId)).catch(() => void 0);
|
|
507
|
-
} catch {
|
|
508
|
-
}
|
|
509
|
-
return true;
|
|
510
|
-
},
|
|
512
|
+
interruptLeader: interruptSession,
|
|
513
|
+
...opts.hqFleetControl ? {
|
|
514
|
+
killFleet: opts.hqFleetControl.killFleet,
|
|
515
|
+
terminateAgent: opts.hqFleetControl.terminateAgent,
|
|
516
|
+
spawnAgent: opts.hqFleetControl.spawnAgent
|
|
517
|
+
} : {},
|
|
511
518
|
allowRunCommand: () => opts.hqAllowExec === true,
|
|
512
519
|
// A command naming a tab this process no longer holds is refused, not
|
|
513
520
|
// redirected onto the boot session: the operator picked a terminal,
|
|
@@ -2237,4 +2244,4 @@ async function runWebUI(opts) {
|
|
|
2237
2244
|
export {
|
|
2238
2245
|
runWebUI
|
|
2239
2246
|
};
|
|
2240
|
-
//# sourceMappingURL=webui-server-
|
|
2247
|
+
//# sourceMappingURL=webui-server-GCXIO3JY.js.map
|
|
@@ -69,6 +69,16 @@ export interface CliWebUIOptions {
|
|
|
69
69
|
* stopping one must never reach into another's fleet.
|
|
70
70
|
*/
|
|
71
71
|
stopSessionFleet?: ((sessionId: string) => void | Promise<void>) | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* The host's interrupt seam. HQ addresses the root conversation through the
|
|
74
|
+
* CLI host's own publisher, whose "abort leader" calls `abortLeader()`; the
|
|
75
|
+
* embedded server binds it to that conversation's run controller.
|
|
76
|
+
*/
|
|
77
|
+
interruptController?: {
|
|
78
|
+
abortLeader: () => boolean;
|
|
79
|
+
} | undefined;
|
|
80
|
+
/** HQ fleet commands for a tab's session (abort fleet / agent, spawn). */
|
|
81
|
+
hqFleetControl?: import('./hq-fleet-control.js').HqFleetControl | undefined;
|
|
72
82
|
/**
|
|
73
83
|
* A tab was closed: release the host-side helpers pinned to its
|
|
74
84
|
* conversation (explore companion, shadow-review bookkeeping).
|
|
@@ -15,6 +15,8 @@ interface CommandHostStateInput {
|
|
|
15
15
|
setConfig: (config: Config) => void;
|
|
16
16
|
getDirector: () => Director | null;
|
|
17
17
|
hqCommandController: HqCommandController;
|
|
18
|
+
/** Several conversations share the Director (WebUI host): see `HqFleetScope`. */
|
|
19
|
+
hqMultiConversation?: boolean | undefined;
|
|
18
20
|
multiAgentHost: MultiAgentHost;
|
|
19
21
|
events: EventBus;
|
|
20
22
|
sessionRef: {
|
|
@@ -36,6 +36,18 @@ interface SetupHqTelemetryDeps {
|
|
|
36
36
|
*/
|
|
37
37
|
approvalMirror?: ApprovalMirrorRef | undefined;
|
|
38
38
|
mcpRegistry: Pick<MCPRegistry, 'onOperation' | 'operationalHealth'>;
|
|
39
|
+
/**
|
|
40
|
+
* The LIVE conversation writer. An in-process `/resume` and an in-place
|
|
41
|
+
* project switch replace `ctx.session`; `session` above is only the boot
|
|
42
|
+
* writer. Defaults to it for hosts that never swap.
|
|
43
|
+
*/
|
|
44
|
+
liveSession?: (() => SessionWriter) | undefined;
|
|
45
|
+
/** The LIVE project root (an in-place project switch re-roots the process). */
|
|
46
|
+
liveProjectRoot?: (() => string) | undefined;
|
|
47
|
+
/** How often the live session/project is compared to what HQ is bound to. */
|
|
48
|
+
scopeCheckIntervalMs?: number | undefined;
|
|
49
|
+
/** The LIVE app config, so `/hq` changes re-point the running connection. */
|
|
50
|
+
getConfig?: (() => Config) | undefined;
|
|
39
51
|
}
|
|
40
52
|
interface HqTelemetryResult {
|
|
41
53
|
hqCommandController: HqCommandController;
|