@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.
Files changed (44) hide show
  1. package/dist/{acp-LI665LO2.js → acp-M4565YUW.js} +30 -17
  2. package/dist/boot/dispatch-singleshot.d.ts +8 -0
  3. package/dist/boot/dispatch-webui.d.ts +2 -0
  4. package/dist/boot/goal-tui-default.d.ts +10 -0
  5. package/dist/{chunk-OAVBM55Q.js → chunk-ENRYW73H.js} +525 -379
  6. package/dist/chunk-HDMFKTT3.js +157 -0
  7. package/dist/{chunk-WQV2NP57.js → chunk-HFZH2XJN.js} +2 -2
  8. package/dist/{chunk-BEHGRNOQ.js → chunk-N57IU5FG.js} +9 -9
  9. package/dist/{chunk-2EBVTYJR.js → chunk-NRXWOMK7.js} +17 -3
  10. package/dist/{chunk-5SEYGOCH.js → chunk-RDGGWMTI.js} +2 -2
  11. package/dist/{chunk-KJS5543T.js → chunk-RGFWGUAB.js} +26 -14
  12. package/dist/{chunk-S4FFHDJG.js → chunk-SDJCLEK6.js} +6 -2
  13. package/dist/{cli-context-UVGAN3NO.js → cli-context-C7RBSWHF.js} +33 -6
  14. package/dist/{cli-main-TN3KZ2P6.js → cli-main-TQTH73ZK.js} +304 -345
  15. package/dist/{execution-7QIP6GRY.js → execution-3STBD2U7.js} +87 -33
  16. package/dist/execution-chimera-review.d.ts +18 -1
  17. package/dist/{hq-GLZ7QESM.js → hq-44F4OQH2.js} +5 -4
  18. package/dist/hq-fleet-control.d.ts +36 -0
  19. package/dist/hq-live-status.d.ts +22 -0
  20. package/dist/hq-publisher.d.ts +18 -0
  21. package/dist/hq-server/routes/command-handlers.d.ts +12 -1
  22. package/dist/hq-server/routes/data-handlers.d.ts +1 -1
  23. package/dist/hq-server/socket-credentials.d.ts +63 -0
  24. package/dist/hq-server/upgrade-handler.d.ts +2 -0
  25. package/dist/hq-server/ws.d.ts +24 -0
  26. package/dist/{hq-server-YTKDVQPY.js → hq-server-UIB24LU6.js} +2 -2
  27. package/dist/{import-claude-code-32PCSIQI.js → import-claude-code-AYG24RG2.js} +36 -4
  28. package/dist/index.js +3 -3
  29. package/dist/live-settings-input.d.ts +1 -0
  30. package/dist/{mailbox-serve-NW5VZG7R.js → mailbox-serve-GNGXEQ2R.js} +2 -2
  31. package/dist/{modeldiag-36VODVIH.js → modeldiag-W7XAE625.js} +2 -2
  32. package/dist/{remote-O5WXHLWV.js → remote-GB5VXCCT.js} +38 -23
  33. package/dist/{sessions-config-SXTTLNXA.js → sessions-config-XHLXJ5C3.js} +75 -6
  34. package/dist/{short-circuit-flags-74Y5N6CF.js → short-circuit-flags-5TNTJPQR.js} +2 -2
  35. package/dist/slash-commands/theme.d.ts +15 -1
  36. package/dist/subcommands/handlers/import-claude-code.d.ts +10 -0
  37. package/dist/subcommands/handlers/sessions-fleet.d.ts +0 -12
  38. package/dist/{subcommands-Q6ORSB2E.js → subcommands-BHQYLDSD.js} +2 -2
  39. package/dist/{webui-server-YTHLRFD2.js → webui-server-GCXIO3JY.js} +37 -30
  40. package/dist/webui-server-options.d.ts +10 -0
  41. package/dist/wiring/command-host-state.d.ts +2 -0
  42. package/dist/wiring/hq-telemetry.d.ts +12 -0
  43. package/package.json +29 -28
  44. 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 reads = mcpEnvPlaceholders(config);
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-32PCSIQI.js.map
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-74Y5N6CF.js");
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-UVGAN3NO.js");
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-TN3KZ2P6.js");
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-KJS5543T.js";
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-NW5VZG7R.js.map
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-S4FFHDJG.js";
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-36VODVIH.js.map
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
- dir=${shPath(path3)}
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
- state="$dir/.wrongstack/remote-webui.json"
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 "$dir/.wrongstack/remote-webui.token")"
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
- mkdir -p .wrongstack
148
- printf '%s' ${shQuote(options.token)} > .wrongstack/remote-webui.token
149
- log=.wrongstack/remote-webui.log
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
- state=$?
175
- if [ "$state" -eq 1 ] && grep -q ${NO_PROVIDER.map((line) => `-e ${shQuote(line)}`).join(" ")} "$log"; then
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
- state=$?
194
+ status=$?
180
195
  fi
181
- if [ "$state" -eq 0 ]; then
182
- printf '{"pid":%s,"port":%s,"version":"%s"}\\n' "$pid" "$port" ${shQuote(options.version)} > .wrongstack/remote-webui.json
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 .wrongstack/remote-webui.token
188
- if [ "$state" -eq 1 ]; then
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
- dir=${shPath(path3)}
201
- state="$dir/.wrongstack/remote-webui.json"
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" "$dir/.wrongstack/remote-webui.token"
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 ${opts.target.path}/.wrongstack/remote-webui.log there.`
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-O5WXHLWV.js.map
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 fsp.readdir(deps.paths.projectSessions);
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
- fsp.readdir(path.join(runDir, "subagents")).then(
73
- (files) => files.filter((f) => f.endsWith(".jsonl")).length,
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 fsp.readdir(subagentsDir);
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-SXTTLNXA.js.map
528
+ //# sourceMappingURL=sessions-config-XHLXJ5C3.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  handleHelpVersionShortCircuit
3
- } from "./chunk-WQV2NP57.js";
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-74Y5N6CF.js.map
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
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  subcommandNames,
3
3
  subcommands
4
- } from "./chunk-BEHGRNOQ.js";
4
+ } from "./chunk-N57IU5FG.js";
5
5
  export {
6
6
  subcommandNames,
7
7
  subcommands
8
8
  };
9
- //# sourceMappingURL=subcommands-Q6ORSB2E.js.map
9
+ //# sourceMappingURL=subcommands-BHQYLDSD.js.map
@@ -11,10 +11,10 @@ import {
11
11
  createHqCommandDispatcher,
12
12
  createProjectKanbanAssignHandler,
13
13
  createProjectKanbanTransitionHandler
14
- } from "./chunk-2EBVTYJR.js";
14
+ } from "./chunk-NRXWOMK7.js";
15
15
  import {
16
16
  startCliHqConnection
17
- } from "./chunk-KJS5543T.js";
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 boot session.
482
- // Announcing it here too would put two trackers on one bus flushing the
483
- // same agent list.
484
- isSessionOwnedElsewhere: (sessionId) => sessionId === opts.session.id,
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
- // HQ speaks for the LEADER — the boot session, the one it registered
490
- // itself under (`hqSessionId`) — not for whatever else the browser
491
- // has open. This used to abort every controller in the map and clear
492
- // it, so a remote "interrupt" issued against the leader also killed
493
- // the three other tabs' in-flight runs. Deleting the entries was
494
- // wrong on its own terms too: the run's own `end()` owns removal, and
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-YTHLRFD2.js.map
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;