@wrongstack/cli 0.300.0 → 0.302.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/{acp-IDNS2YVE.js → acp-DATHHPNT.js} +34 -15
  2. package/dist/acp-server-agent.d.ts +1 -1
  3. package/dist/{audit-2ZSFGNIF.js → audit-QRCLEHHW.js} +5 -1
  4. package/dist/{auth-6T6ZOT2R.js → auth-PJD3JRH2.js} +150 -37
  5. package/dist/boot/dispatch-webui.d.ts +3 -16
  6. package/dist/boot/launch-menu.d.ts +2 -4
  7. package/dist/boot/tool-registry.d.ts +3 -0
  8. package/dist/boot/webui-session-child.d.ts +91 -0
  9. package/dist/chimera-reviewer-policy.d.ts +10 -3
  10. package/dist/chimera-work-registry.d.ts +19 -0
  11. package/dist/{chronicle-QQEQFSSE.js → chronicle-63MFCZN6.js} +26 -5
  12. package/dist/{chunk-YWUPHRGB.js → chunk-263G3FMB.js} +33 -10
  13. package/dist/{chunk-GYDQABMA.js → chunk-2KDOFTTM.js} +44 -32
  14. package/dist/{chunk-V76R7DC5.js → chunk-3MOUBRKZ.js} +311 -309
  15. package/dist/chunk-CSAPOCBP.js +24 -0
  16. package/dist/{chunk-N7ULWBO5.js → chunk-ETOEGL3V.js} +3 -7
  17. package/dist/{chunk-3MWUZMOL.js → chunk-GUHQQG63.js} +14 -3
  18. package/dist/chunk-KE7E7DPX.js +38 -0
  19. package/dist/{chunk-PEMN4T5O.js → chunk-MT6FGXO3.js} +23 -4
  20. package/dist/chunk-PFVVUH5B.js +127 -0
  21. package/dist/{chunk-DPJZQCVP.js → chunk-YMXXOOFN.js} +1 -1
  22. package/dist/{chunk-4WJKVQJY.js → chunk-ZECLGUTF.js} +15 -3
  23. package/dist/cli-context.d.ts +2 -0
  24. package/dist/{cli-main-7B3G2YSG.js → cli-main-EOJ74CI4.js} +336 -99
  25. package/dist/execute-deps.d.ts +3 -0
  26. package/dist/{execution-SHGM7BVC.js → execution-CQ772VPS.js} +246 -97
  27. package/dist/execution-chimera-cascade.d.ts +3 -4
  28. package/dist/execution-chimera-review.d.ts +2 -3
  29. package/dist/execution-cleanup.d.ts +3 -2
  30. package/dist/execution.d.ts +1 -1
  31. package/dist/{export-TPORYVRZ.js → export-DOBGPY23.js} +12 -1
  32. package/dist/fleet/host-context.d.ts +1 -1
  33. package/dist/fleet/host-helpers.d.ts +14 -0
  34. package/dist/fleet/status-broadcast.d.ts +1 -1
  35. package/dist/{hq-DVDD4XPV.js → hq-LN5CJHCM.js} +2 -2
  36. package/dist/hq-server/routes.d.ts +10 -1
  37. package/dist/hq-server/ws.d.ts +17 -6
  38. package/dist/{hq-server-DQHLNHDL.js → hq-server-S7HZG3PA.js} +3 -2
  39. package/dist/index.js +142 -100
  40. package/dist/live-settings-input.d.ts +5 -0
  41. package/dist/{mcp-CYLPUEHC.js → mcp-OHPJH73U.js} +6 -2
  42. package/dist/{modeldiag-YOQZHBQV.js → modeldiag-3DOK4BWW.js} +2 -2
  43. package/dist/{plugin-usage-EOG4ET4S.js → plugin-usage-YEVLOR33.js} +7 -3
  44. package/dist/{plugins-56CMWMPR.js → plugins-K3BAUP4D.js} +3 -3
  45. package/dist/profile-config-path.d.ts +0 -2
  46. package/dist/provider-helpers.d.ts +0 -5
  47. package/dist/{providers-models-K6RT7ABI.js → providers-models-WEZ4EGLL.js} +6 -5
  48. package/dist/{replay-KCTXNMZQ.js → replay-FCBNHW3K.js} +5 -1
  49. package/dist/{rewind-EJMVFVLS.js → rewind-AOD3JIYX.js} +5 -1
  50. package/dist/{sessions-config-NLCMK3BY.js → sessions-config-XXN7267N.js} +8 -3
  51. package/dist/subcommands/flags.d.ts +23 -0
  52. package/dist/terminal-format.d.ts +15 -0
  53. package/dist/{webui-server-G3EKFXLL.js → webui-server-NFNRGNNT.js} +54 -29
  54. package/dist/webui-server-options.d.ts +7 -0
  55. package/dist/wiring/brain-and-orchestration.d.ts +1 -1
  56. package/dist/wiring/mailbox-bridge-bootstrap.d.ts +3 -1
  57. package/dist/wiring/management-tools.d.ts +9 -1
  58. package/dist/wiring/pipeline.d.ts +5 -5
  59. package/dist/wiring/plugins.d.ts +2 -3
  60. package/dist/wiring/provider-utility-tools.d.ts +1 -0
  61. package/dist/wiring/tools.d.ts +4 -5
  62. package/package.json +23 -23
@@ -0,0 +1,24 @@
1
+
2
+ // src/subcommands/flags.ts
3
+ function restoreFlags(args, deps, names) {
4
+ const flags = deps.flags;
5
+ if (!flags) return args;
6
+ const alreadyPresent = new Set(
7
+ args.filter((a) => a.startsWith("-")).map((a) => a.replace(/^-+/, "").split("=")[0]).filter((a) => a !== void 0 && a.length > 0)
8
+ );
9
+ const restored = [];
10
+ for (const name of names) {
11
+ if (alreadyPresent.has(name)) continue;
12
+ const value = flags[name];
13
+ if (value === void 0 || value === false) continue;
14
+ const token = name.length === 1 ? `-${name}` : `--${name}`;
15
+ if (value === true) restored.push(token);
16
+ else restored.push(token, value);
17
+ }
18
+ return restored.length > 0 ? [...args, ...restored] : args;
19
+ }
20
+
21
+ export {
22
+ restoreFlags
23
+ };
24
+ //# sourceMappingURL=chunk-CSAPOCBP.js.map
@@ -1,5 +1,6 @@
1
1
 
2
2
  // src/provider-helpers.ts
3
+ import { hasProviderCredential } from "@wrongstack/core/models";
3
4
  import { catalogProviderIdFor } from "@wrongstack/providers";
4
5
  function uniqueModelIds(primary, fallback) {
5
6
  const seen = /* @__PURE__ */ new Set();
@@ -34,12 +35,7 @@ function isKeylessLocalProvider(provider) {
34
35
  return isLoopbackUrl(provider.apiBase);
35
36
  }
36
37
  function hasApiKey(provider, config) {
37
- if (provider.envVars.some((v) => !!process.env[v])) return true;
38
- const entry = config?.providers?.[provider.id];
39
- if (!entry) return false;
40
- if (typeof entry.apiKey === "string" && entry.apiKey.length > 0) return true;
41
- if (Array.isArray(entry.apiKeys) && entry.apiKeys.some((k) => k?.apiKey)) return true;
42
- return false;
38
+ return hasProviderCredential(provider, config);
43
39
  }
44
40
  async function buildPickableProviders(modelsRegistry, config) {
45
41
  const overlay = config.providers ?? {};
@@ -88,4 +84,4 @@ export {
88
84
  hasApiKey,
89
85
  buildPickableProviders
90
86
  };
91
- //# sourceMappingURL=chunk-N7ULWBO5.js.map
87
+ //# sourceMappingURL=chunk-ETOEGL3V.js.map
@@ -394,7 +394,12 @@ function auditEntryFor(spec) {
394
394
  function officialPluginState(config, spec) {
395
395
  const match = (config.plugins ?? []).find((p) => pluginName(p) === spec);
396
396
  if (!match) return "not configured";
397
- return typeof match === "object" && match.enabled === false ? "disabled" : "enabled";
397
+ const { enabled } = resolvePluginEnablement({
398
+ name: spec,
399
+ config,
400
+ matches: (candidate) => pluginMatchesToggleSpec(candidate, spec)
401
+ });
402
+ return enabled ? "enabled" : "disabled";
398
403
  }
399
404
  async function togglePlugin(spec, deps) {
400
405
  const auditEntry = auditEntryFor(spec);
@@ -405,7 +410,13 @@ async function togglePlugin(spec, deps) {
405
410
  const plugins = Array.isArray(existing.plugins) ? existing.plugins : [];
406
411
  const idx = plugins.findIndex((p) => pluginMatchesToggleSpec(p, spec));
407
412
  const configured = idx >= 0 ? plugins[idx] : void 0;
408
- const enabled = configured ? !(typeof configured === "object" && configured.enabled === false) : auditEntry?.defaultState === "active";
413
+ const effectiveConfig = { ...deps.config, ...existing };
414
+ const { enabled } = resolvePluginEnablement({
415
+ name: spec,
416
+ defaultState: auditEntry?.defaultState,
417
+ config: effectiveConfig,
418
+ matches: (candidate) => pluginMatchesToggleSpec(candidate, spec)
419
+ });
409
420
  if (!configured && !auditEntry) {
410
421
  return errorResult(
411
422
  `Plugin "${spec}" is not configured. Use "wstack plugin add ${spec}" first.`
@@ -497,4 +508,4 @@ export {
497
508
  PLUGIN_AUDIT_ENTRIES,
498
509
  runPluginManagementCommand
499
510
  };
500
- //# sourceMappingURL=chunk-3MWUZMOL.js.map
511
+ //# sourceMappingURL=chunk-GUHQQG63.js.map
@@ -0,0 +1,38 @@
1
+
2
+ // src/terminal-format.ts
3
+ var ANSI = {
4
+ blue: "\x1B[34m",
5
+ cyan: "\x1B[36m",
6
+ green: "\x1B[32m",
7
+ magenta: "\x1B[35m",
8
+ muted: "\x1B[90m",
9
+ success: "\x1B[32m",
10
+ yellow: "\x1B[33m"
11
+ };
12
+ var BOLD = "\x1B[1m";
13
+ var RESET = "\x1B[0m";
14
+ function terminalFormattingEnabled(env = process.env, isTty = Boolean(process.stdout.isTTY)) {
15
+ if (env["NO_COLOR"] !== void 0) return false;
16
+ if (env["FORCE_COLOR"] !== void 0) return true;
17
+ return isTty;
18
+ }
19
+ function terminalText(text, tone, options = {}) {
20
+ const enabled = options.enabled ?? terminalFormattingEnabled();
21
+ if (!enabled) return text;
22
+ return `${options.bold ? BOLD : ""}${ANSI[tone]}${text}${RESET}`;
23
+ }
24
+ function terminalLink(url, options = {}) {
25
+ const enabled = options.enabled ?? terminalFormattingEnabled();
26
+ if (!enabled) return url;
27
+ const visible = terminalText(url, options.tone ?? "cyan", {
28
+ ...options.bold === void 0 ? {} : { bold: options.bold },
29
+ enabled: true
30
+ });
31
+ return `\x1B]8;;${url}\x1B\\${visible}\x1B]8;;\x1B\\`;
32
+ }
33
+
34
+ export {
35
+ terminalText,
36
+ terminalLink
37
+ };
38
+ //# sourceMappingURL=chunk-KE7E7DPX.js.map
@@ -2,11 +2,11 @@ import {
2
2
  hasApiKey,
3
3
  isKeylessLocalProvider,
4
4
  visibleModelIds
5
- } from "./chunk-N7ULWBO5.js";
5
+ } from "./chunk-ETOEGL3V.js";
6
6
  import {
7
7
  appendHistory,
8
8
  backupCurrent
9
- } from "./chunk-YWUPHRGB.js";
9
+ } from "./chunk-263G3FMB.js";
10
10
 
11
11
  // src/arg-parser.ts
12
12
  var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
@@ -33,6 +33,7 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
33
33
  "prompt",
34
34
  "metrics",
35
35
  "webui",
36
+ "webui-session-child",
36
37
  "simpleui",
37
38
  "full-auto",
38
39
  "desktop",
@@ -79,7 +80,24 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
79
80
  // being consumed as the value of one of these switches.
80
81
  "all-models",
81
82
  "plan",
82
- "json"
83
+ "json",
84
+ // Destructive-preview switch (`wstack chronicle prune --dry-run`). It is
85
+ // boolean at every call site, and leaving it out let it consume the next
86
+ // positional — on a command whose whole purpose is to NOT delete.
87
+ "dry-run",
88
+ // Subcommand booleans. A boolean flag missing from this set makes `parseArgs`
89
+ // swallow the FOLLOWING positional as its value (`rewind --all sess123` lost
90
+ // the session id, `export --no-tools out.md` lost the output path), on top of
91
+ // the handler never seeing the flag at all.
92
+ "all",
93
+ "list",
94
+ "latest",
95
+ "disabled",
96
+ "enable",
97
+ "no-tools",
98
+ "no-diagnostics",
99
+ "unsupported",
100
+ "ws"
83
101
  ]);
84
102
  function parseArgs(argv) {
85
103
  const flags = {};
@@ -120,6 +138,7 @@ function parseArgs(argv) {
120
138
  }
121
139
  function normalizeSurfaceAliases(flags, positional) {
122
140
  if (flags["simpleui"]) flags["webui"] = true;
141
+ if (flags["webui-session-child"]) flags["webui"] = true;
123
142
  const first = positional[0];
124
143
  if (first === "simpleui") {
125
144
  flags["simpleui"] = true;
@@ -1020,4 +1039,4 @@ export {
1020
1039
  runLiveProviderPicker,
1021
1040
  runPicker
1022
1041
  };
1023
- //# sourceMappingURL=chunk-PEMN4T5O.js.map
1042
+ //# sourceMappingURL=chunk-MT6FGXO3.js.map
@@ -0,0 +1,127 @@
1
+
2
+ // src/boot/webui-session-child.ts
3
+ import * as fs from "node:fs/promises";
4
+ import * as path from "node:path";
5
+ import { atomicWrite, toErrorMessage } from "@wrongstack/core/utils";
6
+ var WEBUI_SESSION_CHILD_PROTOCOL_VERSION = 1;
7
+ var WEBUI_SESSION_CHILD_CAPABILITIES = [
8
+ "multi-session-child",
9
+ "single-port-http-ws",
10
+ "session-affinity",
11
+ "graceful-shutdown"
12
+ ];
13
+ function flagValue(flags, names) {
14
+ for (const name of names) {
15
+ if (!Object.hasOwn(flags, name)) continue;
16
+ const value = flags[name];
17
+ if (typeof value === "string" && value.trim() !== "") return value.trim();
18
+ throw new Error(`--${name} requires a value`);
19
+ }
20
+ return void 0;
21
+ }
22
+ function boolFlag(flags, names) {
23
+ for (const name of names) {
24
+ if (!Object.hasOwn(flags, name)) continue;
25
+ const value = flags[name];
26
+ if (typeof value === "boolean") return value;
27
+ const normalized = String(value).trim().toLowerCase();
28
+ if (["1", "true", "yes", "on"].includes(normalized)) return true;
29
+ if (["0", "false", "no", "off"].includes(normalized)) return false;
30
+ throw new Error(`--${name} must be a boolean value`);
31
+ }
32
+ return void 0;
33
+ }
34
+ function parsePositiveInteger(value, label) {
35
+ if (value === void 0) throw new Error(`${label} is required`);
36
+ const parsed = Number.parseInt(value, 10);
37
+ if (!Number.isInteger(parsed) || parsed <= 0) throw new Error(`${label} must be a positive integer`);
38
+ return parsed;
39
+ }
40
+ function parsePort(value) {
41
+ if (value === void 0) return void 0;
42
+ const parsed = Number.parseInt(value, 10);
43
+ if (!Number.isInteger(parsed) || parsed <= 0 || parsed > 65535) {
44
+ throw new Error("--port must be a port between 1 and 65535");
45
+ }
46
+ return parsed;
47
+ }
48
+ function requiredString(value, label) {
49
+ if (!value || value.trim() === "") throw new Error(`${label} is required`);
50
+ return value.trim();
51
+ }
52
+ function requireAbsolutePath(value, label) {
53
+ const resolved = requiredString(value, label);
54
+ if (!path.isAbsolute(resolved)) throw new Error(`${label} must be an absolute path`);
55
+ return path.resolve(resolved);
56
+ }
57
+ function parseWebuiSessionChildOptions(flags) {
58
+ if (flags["webui-session-child"] !== true) return null;
59
+ const projectRoot = requireAbsolutePath(flagValue(flags, ["project-root"]), "--project-root");
60
+ const workingDir = requireAbsolutePath(flagValue(flags, ["working-dir"]), "--working-dir");
61
+ const relativeWorkingDir = path.relative(projectRoot, workingDir);
62
+ if (relativeWorkingDir.startsWith("..") || path.isAbsolute(relativeWorkingDir)) {
63
+ throw new Error("--working-dir must be inside --project-root");
64
+ }
65
+ const sessionId = flagValue(flags, ["session-id"]);
66
+ const resume = boolFlag(flags, ["resume"]) ?? false;
67
+ if (sessionId && !resume) throw new Error("--session-id requires --resume");
68
+ if (resume && !sessionId) throw new Error("--resume requires --session-id in child mode");
69
+ const host = flagValue(flags, ["webui-host", "host"]);
70
+ const port = parsePort(flagValue(flags, ["webui-port", "http-port", "port", "ws-port"]));
71
+ const token = flagValue(flags, ["webui-token", "token"]);
72
+ const publicUrl = flagValue(flags, ["webui-public-url", "public-url"]);
73
+ const publicWsUrl = flagValue(flags, ["webui-public-ws-url", "public-ws-url"]);
74
+ const requireToken = boolFlag(flags, ["webui-require-token", "require-token"]);
75
+ return {
76
+ enabled: true,
77
+ projectRoot,
78
+ workingDir,
79
+ ...sessionId ? { sessionId } : {},
80
+ resume,
81
+ ...host ? { host } : {},
82
+ ...port !== void 0 ? { port } : {},
83
+ ...token ? { token } : {},
84
+ ...publicUrl ? { publicUrl } : {},
85
+ ...publicWsUrl ? { publicWsUrl } : {},
86
+ ...requireToken !== void 0 ? { requireToken } : {},
87
+ strictPort: boolFlag(flags, ["strict-port"]) ?? false,
88
+ parentPid: parsePositiveInteger(flagValue(flags, ["parent-pid"]), "--parent-pid"),
89
+ parentShellId: requiredString(flagValue(flags, ["parent-shell-id"]), "--parent-shell-id"),
90
+ runtimeId: requiredString(flagValue(flags, ["runtime-id"]), "--runtime-id"),
91
+ readyFile: requireAbsolutePath(flagValue(flags, ["ready-file"]), "--ready-file"),
92
+ attachable: boolFlag(flags, ["attachable"]) ?? true,
93
+ protocolVersion: parsePositiveInteger(
94
+ flagValue(flags, ["protocol-version"]) ?? String(WEBUI_SESSION_CHILD_PROTOCOL_VERSION),
95
+ "--protocol-version"
96
+ )
97
+ };
98
+ }
99
+ async function writeWebuiSessionChildReady(readyFile, payload) {
100
+ await fs.mkdir(path.dirname(readyFile), { recursive: true });
101
+ await atomicWrite(readyFile, `${JSON.stringify(payload, null, 2)}
102
+ `, { mode: 384 });
103
+ }
104
+ async function writeWebuiSessionChildError(readyFile, input) {
105
+ const payload = {
106
+ type: "webui.session_child.error",
107
+ protocolVersion: input.protocolVersion ?? WEBUI_SESSION_CHILD_PROTOCOL_VERSION,
108
+ ...input.runtimeId ? { runtimeId: input.runtimeId } : {},
109
+ ...input.parentShellId ? { parentShellId: input.parentShellId } : {},
110
+ pid: process.pid,
111
+ phase: input.phase,
112
+ recoverable: input.recoverable,
113
+ message: toErrorMessage(input.error),
114
+ ...input.details ? { details: input.details } : {}
115
+ };
116
+ await fs.mkdir(path.dirname(readyFile), { recursive: true });
117
+ await atomicWrite(readyFile, `${JSON.stringify(payload, null, 2)}
118
+ `, { mode: 384 });
119
+ }
120
+
121
+ export {
122
+ WEBUI_SESSION_CHILD_CAPABILITIES,
123
+ parseWebuiSessionChildOptions,
124
+ writeWebuiSessionChildReady,
125
+ writeWebuiSessionChildError
126
+ };
127
+ //# sourceMappingURL=chunk-PFVVUH5B.js.map
@@ -10,4 +10,4 @@ function activeProfileConfigPath(paths, config) {
10
10
  export {
11
11
  activeProfileConfigPath
12
12
  };
13
- //# sourceMappingURL=chunk-DPJZQCVP.js.map
13
+ //# sourceMappingURL=chunk-YMXXOOFN.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  PLUGIN_AUDIT_ENTRIES
3
- } from "./chunk-3MWUZMOL.js";
3
+ } from "./chunk-GUHQQG63.js";
4
4
  import {
5
5
  patchConfig
6
6
  } from "./chunk-TYO2OVAD.js";
@@ -67,6 +67,10 @@ var BUILTIN_PLUGIN_FACTORIES = [
67
67
  const { createSyncPlugin } = await import("@wrongstack/core/plugin");
68
68
  return createSyncPlugin();
69
69
  },
70
+ async () => {
71
+ const { createCloudConfigSyncPlugin } = await import("@wrongstack/core/plugin");
72
+ return createCloudConfigSyncPlugin();
73
+ },
70
74
  async () => {
71
75
  const { createChimeraPlugin } = await import("@wrongstack/core/plugin");
72
76
  return createChimeraPlugin();
@@ -143,8 +147,16 @@ async function setupPlugins(params) {
143
147
  const userPlugins = [];
144
148
  if (config.features?.plugins !== false) {
145
149
  for (const p of config.plugins ?? []) {
146
- if (typeof p === "object" && p.enabled === false) continue;
147
150
  const spec = typeof p === "string" ? p : p.name;
151
+ const { enabled } = resolvePluginEnablement({
152
+ name: pluginNameFromSpec(spec) ?? spec,
153
+ aliases: [spec],
154
+ defaultState: "active",
155
+ config,
156
+ // The resolver already extracts an entry's name before calling this.
157
+ matches: (configuredName) => configuredName === spec
158
+ });
159
+ if (!enabled) continue;
148
160
  const bareName = pluginNameFromSpec(spec);
149
161
  if (bareName && warnIfDeprecatedPluginName(bareName, log)) {
150
162
  continue;
@@ -250,4 +262,4 @@ export {
250
262
  BUILTIN_PLUGIN_FACTORIES,
251
263
  setupPlugins
252
264
  };
253
- //# sourceMappingURL=chunk-4WJKVQJY.js.map
265
+ //# sourceMappingURL=chunk-ZECLGUTF.js.map
@@ -13,6 +13,7 @@
13
13
  * Returns a `CliContext` object with all the dependencies the rest of
14
14
  * main() needs, or a numeric exit code when a short-circuit fires.
15
15
  */
16
+ import { type WebuiSessionChildOptions } from './boot/webui-session-child.js';
16
17
  import { wireContainer } from './boot/container-wiring.js';
17
18
  import type { EventBus } from '@wrongstack/core/kernel';
18
19
  import type { ConfigStore } from '@wrongstack/core/types';
@@ -22,6 +23,7 @@ export interface CliContext extends BootContext {
22
23
  events: EventBus;
23
24
  container: ReturnType<typeof wireContainer>['container'];
24
25
  configStore: ConfigStore;
26
+ webuiSessionChild?: WebuiSessionChildOptions | undefined;
25
27
  }
26
28
  /**
27
29
  * Run all pre-boot and boot-phase setup. Returns a `CliContext` on success,