@wrongstack/cli 0.310.0 → 0.310.1

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.
@@ -3,7 +3,7 @@ import {
3
3
  loadCachedAcpRegistry,
4
4
  refreshAcpRegistry,
5
5
  setupProvider
6
- } from "./chunk-CHZZEEIP.js";
6
+ } from "./chunk-J4QSP6T2.js";
7
7
  import "./chunk-QYIIOMLE.js";
8
8
  import "./chunk-BXFYBQKR.js";
9
9
  import "./chunk-7OCVIDC7.js";
@@ -913,4 +913,4 @@ ${renderAcpBenchText(result)}
913
913
  export {
914
914
  acpCmd
915
915
  };
916
- //# sourceMappingURL=acp-EA57GUFB.js.map
916
+ //# sourceMappingURL=acp-GZIASCLH.js.map
@@ -0,0 +1,58 @@
1
+ import {
2
+ startProxyProbe
3
+ } from "./chunk-3MAUU765.js";
4
+
5
+ // src/wiring/proxy-wiring.ts
6
+ import {
7
+ applyProxyConfig
8
+ } from "@wrongstack/core/wiring/proxy-rewrite";
9
+ var probeRunner;
10
+ function applyWrongProxyPrefs(payload) {
11
+ const patch = {};
12
+ if (typeof payload["wrongProxyEnabled"] === "boolean") {
13
+ patch.enabled = payload["wrongProxyEnabled"];
14
+ }
15
+ if (typeof payload["wrongProxyUrl"] === "string") {
16
+ patch.url = payload["wrongProxyUrl"];
17
+ }
18
+ if (Object.keys(patch).length === 0) return;
19
+ applyProxyConfig(patch);
20
+ if (!probeRunner) {
21
+ probeRunner = startProxyProbe();
22
+ } else {
23
+ void probeRunner.poke();
24
+ }
25
+ }
26
+ async function awaitFirstWrongProxyProbe() {
27
+ if (!probeRunner) return;
28
+ await probeRunner.poke();
29
+ }
30
+ function bootstrapWrongProxy(snapshot) {
31
+ if (!snapshot) {
32
+ applyWrongProxyPrefs({});
33
+ return;
34
+ }
35
+ const enabled = snapshot.enabled;
36
+ const url = snapshot.url;
37
+ if (typeof enabled === "boolean" || typeof url === "string") {
38
+ const payload = {};
39
+ if (typeof enabled === "boolean") payload["wrongProxyEnabled"] = enabled;
40
+ if (typeof url === "string") payload["wrongProxyUrl"] = url;
41
+ applyWrongProxyPrefs(payload);
42
+ return;
43
+ }
44
+ applyWrongProxyPrefs(snapshot);
45
+ }
46
+ function shutdownWrongProxy() {
47
+ if (probeRunner) probeRunner.stop();
48
+ probeRunner = void 0;
49
+ applyProxyConfig({ enabled: false, url: "", active: false });
50
+ }
51
+
52
+ export {
53
+ applyWrongProxyPrefs,
54
+ awaitFirstWrongProxyProbe,
55
+ bootstrapWrongProxy,
56
+ shutdownWrongProxy
57
+ };
58
+ //# sourceMappingURL=chunk-3FHFGIIN.js.map
@@ -0,0 +1,120 @@
1
+
2
+ // src/wiring/proxy-probe.ts
3
+ import { applyProxyConfig, getProxyConfig } from "@wrongstack/core/wiring/proxy-rewrite";
4
+ var DEFAULT_INTERVAL_MS = 3e4;
5
+ var DEFAULT_TIMEOUT_MS = 2e3;
6
+ var HEALTH_PATH = "/api/health";
7
+ var DEFAULT_DEACTIVATE_AFTER_FAILURES = 2;
8
+ var activeRunner;
9
+ function startProxyProbe(opts = {}) {
10
+ if (activeRunner) {
11
+ scheduleImmediateProbe(activeRunner);
12
+ return activeRunner;
13
+ }
14
+ const intervalMs = opts.intervalMs ?? DEFAULT_INTERVAL_MS;
15
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
16
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
17
+ const setIntervalImpl = opts.setIntervalImpl ?? setInterval;
18
+ const clearIntervalImpl = opts.clearIntervalImpl ?? clearInterval;
19
+ const deactivateAfterFailures = typeof opts.deactivateAfterFailures === "number" && Number.isFinite(opts.deactivateAfterFailures) ? Math.max(1, Math.trunc(opts.deactivateAfterFailures)) : DEFAULT_DEACTIVATE_AFTER_FAILURES;
20
+ const state = {
21
+ currentAbort: void 0,
22
+ timer: void 0,
23
+ // Consecutive failed probes. Reset on every success; `active` flips to
24
+ // false only once this reaches `deactivateAfterFailures`. A single
25
+ // transient failure is a soft signal and must not disable rewrites.
26
+ consecutiveFailures: 0
27
+ };
28
+ const runOnce = async () => {
29
+ const cfg = getProxyConfig();
30
+ if (!cfg.enabled || !cfg.url) {
31
+ state.consecutiveFailures = 0;
32
+ if (state.currentAbort) state.currentAbort.abort();
33
+ state.currentAbort = void 0;
34
+ applyProxyConfig({ active: false });
35
+ return false;
36
+ }
37
+ if (state.currentAbort) state.currentAbort.abort();
38
+ const abort = new AbortController();
39
+ state.currentAbort = abort;
40
+ let timedOut = false;
41
+ const timeout = setTimeout(() => {
42
+ timedOut = true;
43
+ abort.abort();
44
+ }, timeoutMs);
45
+ if (typeof timeout.unref === "function") {
46
+ timeout.unref();
47
+ }
48
+ try {
49
+ const healthUrl = buildHealthUrl(cfg.url);
50
+ const res = await fetchImpl(healthUrl, {
51
+ method: "GET",
52
+ signal: abort.signal,
53
+ headers: { accept: "application/json" }
54
+ });
55
+ const ok = res.ok && res.status >= 200 && res.status < 300;
56
+ const live = getProxyConfig();
57
+ const stillRelevant = live.enabled && live.url === cfg.url;
58
+ if (stillRelevant) {
59
+ if (ok) {
60
+ state.consecutiveFailures = 0;
61
+ applyProxyConfig({ active: true });
62
+ } else {
63
+ state.consecutiveFailures += 1;
64
+ if (state.consecutiveFailures >= deactivateAfterFailures) {
65
+ applyProxyConfig({ active: false });
66
+ }
67
+ }
68
+ }
69
+ return ok;
70
+ } catch {
71
+ const live = getProxyConfig();
72
+ const stillRelevant = live.enabled && live.url === cfg.url;
73
+ if (stillRelevant && (timedOut || !abort.signal.aborted)) {
74
+ state.consecutiveFailures += 1;
75
+ if (state.consecutiveFailures >= deactivateAfterFailures) {
76
+ applyProxyConfig({ active: false });
77
+ }
78
+ }
79
+ return false;
80
+ } finally {
81
+ clearTimeout(timeout);
82
+ if (state.currentAbort === abort) state.currentAbort = void 0;
83
+ }
84
+ };
85
+ const runner = {
86
+ stop() {
87
+ if (state.timer !== void 0) {
88
+ clearIntervalImpl(state.timer);
89
+ state.timer = void 0;
90
+ }
91
+ if (state.currentAbort) {
92
+ state.currentAbort.abort();
93
+ state.currentAbort = void 0;
94
+ }
95
+ activeRunner = void 0;
96
+ },
97
+ poke: runOnce
98
+ };
99
+ scheduleImmediateProbe(runner);
100
+ state.timer = setIntervalImpl(() => {
101
+ void runOnce();
102
+ }, intervalMs);
103
+ if (state.timer && typeof state.timer.unref === "function") {
104
+ state.timer.unref();
105
+ }
106
+ activeRunner = runner;
107
+ return runner;
108
+ }
109
+ function scheduleImmediateProbe(runner) {
110
+ void runner.poke();
111
+ }
112
+ function buildHealthUrl(rawBase) {
113
+ const trimmed = rawBase.trim().replace(/\/+$/, "");
114
+ return `${trimmed}${HEALTH_PATH}`;
115
+ }
116
+
117
+ export {
118
+ startProxyProbe
119
+ };
120
+ //# sourceMappingURL=chunk-3MAUU765.js.map
@@ -166,7 +166,7 @@ Update failed: ${msg}
166
166
  var updateCmd = async (args, deps) => runUpdateCommand(args, deps);
167
167
  function writeUpdateUsage(renderer) {
168
168
  renderer.write(
169
- "Usage: wrongstack update [--check-only] [--pm npm|pnpm|yarn|bun] [--allow-scripts]\n"
169
+ "Usage: wstack update [--check-only] [--pm <manager>] [--allow-scripts (alias: --lifecycle-scripts)]\n"
170
170
  );
171
171
  }
172
172
  function mergeUpdateArgs(args, flags) {
@@ -383,4 +383,4 @@ export {
383
383
  detectUpdatePackageManager,
384
384
  detectUpdatePackageName
385
385
  };
386
- //# sourceMappingURL=chunk-63GFD62R.js.map
386
+ //# sourceMappingURL=chunk-4S52MIIM.js.map
@@ -2841,7 +2841,7 @@ async function handleApiAgentMessages(req, res, match, agentMessages) {
2841
2841
  async function handleApiSystemUpdate(res) {
2842
2842
  const [{ checkForUpdate }, { detectUpdatePackageName }] = await Promise.all([
2843
2843
  import("./update-check-WARHSVZA.js"),
2844
- import("./update-RATFF63M.js")
2844
+ import("./update-ZXNC6I6G.js")
2845
2845
  ]);
2846
2846
  const packageName = detectUpdatePackageName();
2847
2847
  const info = await checkForUpdate({ packageName });
@@ -4916,4 +4916,4 @@ export {
4916
4916
  startHqServer,
4917
4917
  HqInsecureExposureError2 as HqInsecureExposureError
4918
4918
  };
4919
- //# sourceMappingURL=chunk-KQNYSZG2.js.map
4919
+ //# sourceMappingURL=chunk-J3XBHGEO.js.map
@@ -42,6 +42,37 @@ async function refreshAcpRegistry(paths, opts) {
42
42
  return { count: result.agents.length, location, fetchedAt: result.fetchedAt };
43
43
  }
44
44
 
45
+ // src/wiring/provider-runtime.ts
46
+ import { makeProviderFromConfig } from "@wrongstack/providers";
47
+ import { getProxyConfig, rewriteBaseUrl, shouldRewriteFor } from "@wrongstack/core/wiring/proxy-rewrite";
48
+ function resolveProviderCfg(config, providerId) {
49
+ const savedCfg = config.providers?.[providerId];
50
+ const rawBaseUrl = savedCfg?.baseUrl ?? config.baseUrl;
51
+ const baseUrl = rawBaseUrl && shouldRewriteFor(providerId) ? rewriteBaseUrl(rawBaseUrl, currentProxyBaseUrl()) : rawBaseUrl;
52
+ const cfg = {
53
+ ...savedCfg,
54
+ apiKey: savedCfg?.apiKey ?? config.apiKey,
55
+ baseUrl,
56
+ type: providerId
57
+ };
58
+ const factoryType = savedCfg?.type ?? providerId;
59
+ return { cfg, factoryType };
60
+ }
61
+ function currentProxyBaseUrl() {
62
+ return getProxyConfig().url;
63
+ }
64
+ function resolveProviderCfgWithProxy(config, providerId) {
65
+ return resolveProviderCfg(config, providerId);
66
+ }
67
+ function buildProviderForId(args, providerId) {
68
+ const { cfg, factoryType } = resolveProviderCfg(args.config, providerId);
69
+ const useRegistry = !!args.config.features.modelsRegistry && args.providerRegistry.has(factoryType);
70
+ return useRegistry ? args.providerRegistry.create(cfg, factoryType) : makeProviderFromConfig(
71
+ providerId,
72
+ factoryType === "ai-gateway" ? { ...cfg, type: factoryType } : cfg
73
+ );
74
+ }
75
+
45
76
  // src/shutdown-cleanup.ts
46
77
  function createGracefulShutdown(cleanup) {
47
78
  const exitCode = cleanup.exitCode ?? 0;
@@ -92,7 +123,7 @@ import {
92
123
  buildProviderFactoriesFromRegistry,
93
124
  createAiGatewayProviderFactory,
94
125
  installCatalogModelOutputLimits,
95
- makeProviderFromConfig,
126
+ makeProviderFromConfig as makeProviderFromConfig2,
96
127
  withCatalogCapabilities
97
128
  } from "@wrongstack/providers";
98
129
  async function setupProvider(params) {
@@ -174,19 +205,17 @@ Try \`wstack models refresh\` once you have network access, or run with --no-fea
174
205
  });
175
206
  }
176
207
  }
177
- const providerConfig = config.providers?.[config.provider] ?? {
178
- type: config.provider,
179
- apiKey: config.apiKey,
180
- baseUrl: config.baseUrl
181
- };
208
+ const { cfg: providerConfig, factoryType } = resolveProviderCfgWithProxy(
209
+ config,
210
+ config.provider
211
+ );
182
212
  let provider;
183
213
  try {
184
- const factoryType = providerConfig.type ?? config.provider;
185
214
  const cfgWithType = { ...providerConfig, type: config.provider };
186
215
  if (providerRegistry.has(factoryType)) {
187
216
  provider = providerRegistry.create(cfgWithType, factoryType);
188
217
  } else {
189
- provider = makeProviderFromConfig(config.provider, { ...cfgWithType, type: factoryType });
218
+ provider = makeProviderFromConfig2(config.provider, { ...cfgWithType, type: factoryType });
190
219
  }
191
220
  } catch (err) {
192
221
  throw new ConfigError({
@@ -211,7 +240,9 @@ Try \`wstack models refresh\` once you have network access, or run with --no-fea
211
240
  export {
212
241
  loadCachedAcpRegistry,
213
242
  refreshAcpRegistry,
243
+ resolveProviderCfg,
244
+ buildProviderForId,
214
245
  setupProvider,
215
246
  createGracefulShutdown
216
247
  };
217
- //# sourceMappingURL=chunk-CHZZEEIP.js.map
248
+ //# sourceMappingURL=chunk-J4QSP6T2.js.map
@@ -25,12 +25,6 @@ import {
25
25
  runGit,
26
26
  setSuggestions
27
27
  } from "./chunk-X3N5TS2S.js";
28
- import {
29
- setupPlugins
30
- } from "./chunk-BZJ4MP32.js";
31
- import {
32
- startCliHqConnection
33
- } from "./chunk-FKWHSFX4.js";
34
28
  import {
35
29
  advanceToNextTask,
36
30
  findSpec,
@@ -41,10 +35,21 @@ import {
41
35
  matchTaskNode,
42
36
  sddState
43
37
  } from "./chunk-DGXNL7OT.js";
38
+ import {
39
+ setupPlugins
40
+ } from "./chunk-BZJ4MP32.js";
41
+ import {
42
+ startCliHqConnection
43
+ } from "./chunk-FKWHSFX4.js";
44
+ import {
45
+ awaitFirstWrongProxyProbe,
46
+ bootstrapWrongProxy
47
+ } from "./chunk-3FHFGIIN.js";
44
48
  import {
45
49
  PLUGIN_AUDIT_ENTRIES,
46
50
  runPluginManagementCommand
47
51
  } from "./chunk-H6C7SO5H.js";
52
+ import "./chunk-3MAUU765.js";
48
53
  import {
49
54
  configureSimpleUiRuntimeContext,
50
55
  detectProjectFacts,
@@ -67,11 +72,13 @@ import {
67
72
  CLI_VERSION
68
73
  } from "./chunk-XJXDOF63.js";
69
74
  import {
75
+ buildProviderForId,
70
76
  createGracefulShutdown,
71
77
  loadCachedAcpRegistry,
72
78
  refreshAcpRegistry,
79
+ resolveProviderCfg,
73
80
  setupProvider
74
- } from "./chunk-CHZZEEIP.js";
81
+ } from "./chunk-J4QSP6T2.js";
75
82
  import {
76
83
  addCustomProvider,
77
84
  addKeyForCatalogProvider,
@@ -354,6 +361,8 @@ async function resolveModeAndCapabilities(deps) {
354
361
  let providerRegistry;
355
362
  let provider;
356
363
  try {
364
+ bootstrapWrongProxy(deps.config.tools?.wrongProxy);
365
+ await awaitFirstWrongProxyProbe();
357
366
  const result = await setupProvider({
358
367
  config: deps.config,
359
368
  modelsRegistry: deps.modelsRegistry,
@@ -1944,6 +1953,11 @@ function makeProviderClassifier(provider, model) {
1944
1953
 
1945
1954
  // src/fleet/host-provider.ts
1946
1955
  import { makeProviderFromConfig, withCatalogCapabilities } from "@wrongstack/providers";
1956
+ import {
1957
+ getProxyConfig,
1958
+ rewriteBaseUrl,
1959
+ shouldRewriteFor
1960
+ } from "@wrongstack/core/wiring/proxy-rewrite";
1947
1961
  async function buildHostSubagentProvider(deps, config, overrideId, model) {
1948
1962
  const requestedProviderId = overrideId ?? config.provider;
1949
1963
  const providerId = requestedProviderId === config.provider || config.providers?.[requestedProviderId] !== void 0 || deps.providerRegistry.has(requestedProviderId) ? requestedProviderId : config.provider;
@@ -1952,9 +1966,13 @@ async function buildHostSubagentProvider(deps, config, overrideId, model) {
1952
1966
  apiKey: config.apiKey,
1953
1967
  baseUrl: config.baseUrl
1954
1968
  };
1969
+ const factoryType = newCfg.type ?? providerId;
1970
+ const rawBaseUrl = newCfg.baseUrl ?? config.baseUrl;
1971
+ const baseUrl = rawBaseUrl && shouldRewriteFor(factoryType) ? rewriteBaseUrl(rawBaseUrl, getProxyConfig().url) : rawBaseUrl;
1955
1972
  const cfgWithType = {
1956
1973
  ...newCfg,
1957
1974
  type: providerId,
1975
+ ...baseUrl !== newCfg.baseUrl ? { baseUrl } : {},
1958
1976
  ...model ? { model } : {}
1959
1977
  };
1960
1978
  let provider = deps.providerRegistry.has(providerId) ? deps.providerRegistry.create(cfgWithType) : makeProviderFromConfig(providerId, cfgWithType);
@@ -3927,28 +3945,6 @@ var MultiAgentHost = class {
3927
3945
  }
3928
3946
  };
3929
3947
 
3930
- // src/wiring/provider-runtime.ts
3931
- import { makeProviderFromConfig as makeProviderFromConfig2 } from "@wrongstack/providers";
3932
- function resolveProviderCfg(config, providerId) {
3933
- const savedCfg = config.providers?.[providerId];
3934
- const cfg = {
3935
- ...savedCfg,
3936
- apiKey: savedCfg?.apiKey ?? config.apiKey,
3937
- baseUrl: savedCfg?.baseUrl ?? config.baseUrl,
3938
- type: providerId
3939
- };
3940
- const factoryType = savedCfg?.type ?? providerId;
3941
- return { cfg, factoryType };
3942
- }
3943
- function buildProviderForId(args, providerId) {
3944
- const { cfg, factoryType } = resolveProviderCfg(args.config, providerId);
3945
- const useRegistry = !!args.config.features.modelsRegistry && args.providerRegistry.has(factoryType);
3946
- return useRegistry ? args.providerRegistry.create(cfg, factoryType) : makeProviderFromConfig2(
3947
- providerId,
3948
- factoryType === "ai-gateway" ? { ...cfg, type: factoryType } : cfg
3949
- );
3950
- }
3951
-
3952
3948
  // src/wiring/brain-and-orchestration.ts
3953
3949
  function setupBrainAndOrchestration(deps) {
3954
3950
  const {
@@ -4812,6 +4808,26 @@ function applyLiveSettings(input, settings) {
4812
4808
  });
4813
4809
  }
4814
4810
  }
4811
+ if (settings.wrongProxyEnabled !== void 0 || settings.wrongProxyUrl !== void 0) {
4812
+ const prev = config.tools?.wrongProxy;
4813
+ const next = {
4814
+ ...prev ?? {},
4815
+ ...settings.wrongProxyEnabled !== void 0 ? { enabled: settings.wrongProxyEnabled } : {},
4816
+ ...settings.wrongProxyUrl !== void 0 ? { url: settings.wrongProxyUrl } : {}
4817
+ };
4818
+ config = patchConfig(config, {
4819
+ tools: {
4820
+ ...config.tools,
4821
+ wrongProxy: next
4822
+ }
4823
+ });
4824
+ if (settings.wrongProxyEnabled !== void 0) {
4825
+ input.context.meta["wrongProxyEnabled"] = settings.wrongProxyEnabled;
4826
+ }
4827
+ if (settings.wrongProxyUrl !== void 0) {
4828
+ input.context.meta["wrongProxyUrl"] = settings.wrongProxyUrl;
4829
+ }
4830
+ }
4815
4831
  input.setConfig(config);
4816
4832
  } catch {
4817
4833
  }
@@ -5131,7 +5147,7 @@ async function runCliExecution(params) {
5131
5147
  governanceHandle,
5132
5148
  setConfig
5133
5149
  } = params;
5134
- const { execute } = await import("./execution-WA2UCXNM.js");
5150
+ const { execute } = await import("./execution-ZEHK4II6.js");
5135
5151
  return execute(
5136
5152
  toExecuteDeps({
5137
5153
  core: {
@@ -33933,6 +33949,8 @@ async function runInteractive(cliCtx) {
33933
33949
  logger,
33934
33950
  teardownHandlers
33935
33951
  });
33952
+ bootstrapWrongProxy(config.tools?.wrongProxy);
33953
+ await awaitFirstWrongProxyProbe();
33936
33954
  const { buildProviderForId: buildProviderForId2, buildProviderForModel, switchProviderAndModel } = setupProviderRuntime({
33937
33955
  config,
33938
33956
  onConfigUpdate: (newConfig) => {
@@ -34367,4 +34385,4 @@ export {
34367
34385
  CLI_VERSION,
34368
34386
  runInteractive
34369
34387
  };
34370
- //# sourceMappingURL=cli-main-RFEZAJ4U.js.map
34388
+ //# sourceMappingURL=cli-main-UDWMWX55.js.map
@@ -1,3 +1,6 @@
1
+ import {
2
+ startProxyProbe
3
+ } from "./chunk-3MAUU765.js";
1
4
  import {
2
5
  API_VERSION
3
6
  } from "./chunk-XJXDOF63.js";
@@ -8,6 +11,11 @@ import * as fs2 from "node:fs/promises";
8
11
  import * as os from "node:os";
9
12
  import * as path2 from "node:path";
10
13
  import { color, toErrorMessage } from "@wrongstack/core/utils";
14
+ import {
15
+ applyProxyConfig,
16
+ getProxyConfig,
17
+ shouldRewriteFor
18
+ } from "@wrongstack/core/wiring/proxy-rewrite";
11
19
 
12
20
  // src/subcommands/handlers/daemon-inventory.ts
13
21
  import * as fs from "node:fs/promises";
@@ -138,6 +146,43 @@ var diagCmd = async (_args, deps) => {
138
146
  deps.renderer.write(lines.join("\n") + "\n");
139
147
  return 0;
140
148
  };
149
+ var proxyCmd = async (_args, deps) => {
150
+ const persisted = deps.config.tools?.wrongProxy;
151
+ if (persisted) {
152
+ applyProxyConfig({
153
+ enabled: persisted.enabled === true,
154
+ url: typeof persisted.url === "string" ? persisted.url : ""
155
+ });
156
+ }
157
+ if (persisted?.enabled === true && persisted.url) {
158
+ const runner = startProxyProbe({ intervalMs: 6e4, timeoutMs: 2e3 });
159
+ await runner.poke();
160
+ }
161
+ const cfg = getProxyConfig();
162
+ const gate = shouldRewriteFor("openai");
163
+ const enabled = cfg.enabled;
164
+ const url = cfg.url || "<unset>";
165
+ const active = cfg.active;
166
+ const status = () => {
167
+ if (enabled && active && cfg.url) return { glyph: "\u2713", label: "live", color: color.green };
168
+ if (enabled && !active)
169
+ return { glyph: "\u25CF", label: "enabled, probe not yet active", color: color.amber };
170
+ if (!enabled && cfg.url)
171
+ return { glyph: "\u25CB", label: "url set, toggle off", color: color.dim };
172
+ return { glyph: "\xB7", label: "unconfigured", color: color.dim };
173
+ };
174
+ const s = status();
175
+ const rewriteGateLabel = (open) => open ? color.green("rewrites applied") : color.dim("rewrites bypassed");
176
+ const lines = [
177
+ color.bold("WrongProxy / WrongTrace status"),
178
+ ` enabled: ${enabled}`,
179
+ ` url: ${url}`,
180
+ ` active: ${active} ${s.color(`(${s.label})`)}`,
181
+ ` shouldRewrite:${gate} ${rewriteGateLabel(gate)}`
182
+ ];
183
+ deps.renderer.write(lines.join("\n") + "\n");
184
+ return 0;
185
+ };
141
186
  async function reportDaemons(deps, opts) {
142
187
  const inventory = { projectRoot: deps.projectRoot, projectDir: deps.paths.projectDir };
143
188
  let reports = await collectDaemonReports(inventory);
@@ -324,6 +369,7 @@ var doctorCmd = async (args, deps) => {
324
369
  };
325
370
  export {
326
371
  diagCmd,
327
- doctorCmd
372
+ doctorCmd,
373
+ proxyCmd
328
374
  };
329
- //# sourceMappingURL=diag-doctor-HJKFUY6B.js.map
375
+ //# sourceMappingURL=diag-doctor-Z6JDXBVX.js.map
@@ -9,9 +9,6 @@ import {
9
9
  setAutoSuggestions,
10
10
  setSuggestions
11
11
  } from "./chunk-X3N5TS2S.js";
12
- import {
13
- startCliHqConnection
14
- } from "./chunk-FKWHSFX4.js";
15
12
  import "./chunk-WHOIR577.js";
16
13
  import {
17
14
  advanceToNextTask,
@@ -26,6 +23,9 @@ import {
26
23
  trySaveSpecFromAIOutput,
27
24
  trySaveTasksFromAIOutput
28
25
  } from "./chunk-DGXNL7OT.js";
26
+ import {
27
+ startCliHqConnection
28
+ } from "./chunk-FKWHSFX4.js";
29
29
  import {
30
30
  theme
31
31
  } from "./chunk-QD544J2B.js";
@@ -207,7 +207,7 @@ async function runWebUIDispatch(ctx) {
207
207
  const isSimpleUi = !isSessionChild && flags["simpleui"] === true;
208
208
  agent.disableInteractiveConfirmation();
209
209
  renderer.setSilent(true);
210
- const { runWebUI } = await import("./webui-server-3DU6BVTB.js");
210
+ const { runWebUI } = await import("./webui-server-UB75UHWX.js");
211
211
  const flagValue = (names) => {
212
212
  for (const name of names) {
213
213
  if (!Object.hasOwn(flags, name)) continue;
@@ -404,6 +404,11 @@ async function runWebUIDispatch(ctx) {
404
404
  },
405
405
  onYoloSwitch: (enabled) => {
406
406
  applyLiveSettings?.({ yolo: enabled });
407
+ },
408
+ onWrongProxyPrefsChange: (payload) => {
409
+ void import("./proxy-wiring-7RPGBHZP.js").then(
410
+ ({ applyWrongProxyPrefs }) => applyWrongProxyPrefs(payload)
411
+ );
407
412
  }
408
413
  });
409
414
  const webuiExit = new Promise((resolve4) => {
@@ -1716,12 +1721,23 @@ function createSettingsAdapter(ctx) {
1716
1721
  }),
1717
1722
  showSageMemoryInject: autonomy?.showSageMemoryInject ?? false,
1718
1723
  readSymbols: autonomy?.readAdvancedMode ?? false,
1719
- sageMemoryInjectThreshold: cfg.Sage?.inject ? cfg.Sage.inject?.relationFloor : void 0
1724
+ sageMemoryInjectThreshold: cfg.Sage?.inject ? cfg.Sage.inject?.relationFloor : void 0,
1725
+ // WrongProxy / WrongTrace: read from `tools.wrongProxy.{enabled,url}`
1726
+ // so the persistence shape mirrors the WebUI `LocalPrefs` shape
1727
+ // (single object with two fields, not two top-level keys). The
1728
+ // canonical type is `ToolsConfig.wrongProxy?: WrongProxyToolConfig`
1729
+ // — no index-signature widening cast needed.
1730
+ wrongProxyEnabled: cfg.tools?.wrongProxy?.enabled === true,
1731
+ wrongProxyUrl: cfg.tools?.wrongProxy?.url
1720
1732
  };
1721
1733
  }
1722
1734
  async function saveSettings(s) {
1723
1735
  try {
1724
- if (s.mode !== void 0 || s.delayMs !== void 0 || s.titleAnimation !== void 0 || s.yolo !== void 0 || s.fleetChatVerbosity !== void 0 || s.chime !== void 0 || s.confirmExit !== void 0 || s.mouseMode !== void 0 || s.featureMcp !== void 0 || s.featurePlugins !== void 0 || s.featureMemory !== void 0 || s.featureSkills !== void 0 || s.featureModelsRegistry !== void 0 || s.featureTokenSaving !== void 0 || s.allowOutsideProjectRoot !== void 0 || s.contextAutoCompact !== void 0 || s.contextStrategy !== void 0 || s.contextMode !== void 0 || s.maxConcurrent !== void 0 || s.logLevel !== void 0 || s.auditLevel !== void 0 || s.indexOnStart !== void 0 || s.maxIterations !== void 0 || s.nextStepsTool !== void 0 || s.restrictFsToRoot !== void 0 || s.nextPrediction !== void 0 || s.debugStream !== void 0 || s.shellBangWarningDontShowAgain !== void 0 || s.configScope !== void 0 || s.enhanceDelayMs !== void 0 || s.enhanceEnabled !== void 0 || s.enhanceLanguage !== void 0 || s.midRunSendPicker !== void 0 || s.statuslineMode !== void 0 || s.thinkingWord !== void 0 || s.animationStyle !== void 0 || s.autonomyNextPrompt !== void 0 || s.autoProceedMaxIterations !== void 0 || s.reasoningMode !== void 0 || s.reasoningEffort !== void 0 || s.reasoningPreserve !== void 0 || s.cacheTtl !== void 0 || s.breakerEnabled !== void 0 || s.breakerAutoKillResetMs !== void 0 || s.showModelReasoning !== void 0 || s.showAgentSwarmPanel !== void 0 || s.panelPositions !== void 0 || s.showSageMemoryInject !== void 0 || s.sageMemoryInjectThreshold !== void 0 || s.readSymbols !== void 0) {
1736
+ if (s.mode !== void 0 || s.delayMs !== void 0 || s.titleAnimation !== void 0 || s.yolo !== void 0 || s.fleetChatVerbosity !== void 0 || s.chime !== void 0 || s.confirmExit !== void 0 || s.mouseMode !== void 0 || s.featureMcp !== void 0 || s.featurePlugins !== void 0 || s.featureMemory !== void 0 || s.featureSkills !== void 0 || s.featureModelsRegistry !== void 0 || s.featureTokenSaving !== void 0 || s.allowOutsideProjectRoot !== void 0 || s.contextAutoCompact !== void 0 || s.contextStrategy !== void 0 || s.contextMode !== void 0 || s.maxConcurrent !== void 0 || s.logLevel !== void 0 || s.auditLevel !== void 0 || s.indexOnStart !== void 0 || s.maxIterations !== void 0 || s.nextStepsTool !== void 0 || s.restrictFsToRoot !== void 0 || s.nextPrediction !== void 0 || s.debugStream !== void 0 || s.shellBangWarningDontShowAgain !== void 0 || s.configScope !== void 0 || s.enhanceDelayMs !== void 0 || s.enhanceEnabled !== void 0 || s.enhanceLanguage !== void 0 || s.midRunSendPicker !== void 0 || s.statuslineMode !== void 0 || s.thinkingWord !== void 0 || s.animationStyle !== void 0 || s.autonomyNextPrompt !== void 0 || s.autoProceedMaxIterations !== void 0 || s.reasoningMode !== void 0 || s.reasoningEffort !== void 0 || s.reasoningPreserve !== void 0 || s.cacheTtl !== void 0 || s.breakerEnabled !== void 0 || s.breakerAutoKillResetMs !== void 0 || s.showModelReasoning !== void 0 || s.showAgentSwarmPanel !== void 0 || s.panelPositions !== void 0 || s.showSageMemoryInject !== void 0 || s.sageMemoryInjectThreshold !== void 0 || s.readSymbols !== void 0 || // WrongProxy / WrongTrace: gate the persisted-section write on
1737
+ // either key being present in the live patch. Without this, a
1738
+ // picker toggle round-trip would silently no-op the persistence
1739
+ // layer (the runtime probe would never read the change).
1740
+ s.wrongProxyEnabled !== void 0 || s.wrongProxyUrl !== void 0) {
1725
1741
  const cfg = configStore.get();
1726
1742
  const persistDeps = {
1727
1743
  configStore,
@@ -1819,11 +1835,21 @@ function createSettingsAdapter(ctx) {
1819
1835
  idx.onSessionStart = s.indexOnStart;
1820
1836
  decrypted.indexing = idx;
1821
1837
  }
1822
- if (s.maxIterations !== void 0 || s.nextStepsTool !== void 0 || fsAccess !== void 0) {
1838
+ if (s.maxIterations !== void 0 || s.nextStepsTool !== void 0 || fsAccess !== void 0 || // WrongProxy / WrongTrace: include either key in the tools-section
1839
+ // write guard so a picker toggle round-trip actually persists to
1840
+ // `tools.wrongProxy.{enabled,url}`. Without this, the gate at
1841
+ // line 279 would short-circuit and skip the whole section write.
1842
+ s.wrongProxyEnabled !== void 0 || s.wrongProxyUrl !== void 0) {
1823
1843
  const tools = decrypted.tools ?? {};
1824
1844
  if (s.maxIterations !== void 0) tools.maxIterations = s.maxIterations;
1825
1845
  if (s.nextStepsTool !== void 0) tools.nextsteps = { enabled: s.nextStepsTool };
1826
1846
  if (fsAccess !== void 0) tools.restrictToProjectRoot = fsAccess.restrictToProjectRoot;
1847
+ if (s.wrongProxyEnabled !== void 0 || s.wrongProxyUrl !== void 0) {
1848
+ const wp = tools.wrongProxy ?? {};
1849
+ if (s.wrongProxyEnabled !== void 0) wp.enabled = s.wrongProxyEnabled;
1850
+ if (s.wrongProxyUrl !== void 0) wp.url = s.wrongProxyUrl;
1851
+ tools.wrongProxy = wp;
1852
+ }
1827
1853
  decrypted.tools = tools;
1828
1854
  }
1829
1855
  if (s.debugStream !== void 0) {
@@ -1934,7 +1960,11 @@ function createSettingsAdapter(ctx) {
1934
1960
  ...decrypted.indexing ?? {}
1935
1961
  }
1936
1962
  } : {},
1937
- ...s.maxIterations !== void 0 || s.nextStepsTool !== void 0 || fsAccess !== void 0 ? {
1963
+ ...s.maxIterations !== void 0 || s.nextStepsTool !== void 0 || fsAccess !== void 0 || // WrongProxy / WrongTrace: must be in the tools guard or the
1964
+ // in-memory ConfigStore never sees the freshly-saved values,
1965
+ // and the next picker open in the same process would overwrite
1966
+ // the on-disk selection with stale state. See Chimera review.
1967
+ s.wrongProxyEnabled !== void 0 || s.wrongProxyUrl !== void 0 ? {
1938
1968
  tools: {
1939
1969
  ...currentConfig.tools,
1940
1970
  ...decrypted.tools ?? {}
@@ -6213,4 +6243,4 @@ export {
6213
6243
  execute,
6214
6244
  resolveReviewerFallbackModels
6215
6245
  };
6216
- //# sourceMappingURL=execution-WA2UCXNM.js.map
6246
+ //# sourceMappingURL=execution-ZEHK4II6.js.map
@@ -51,7 +51,7 @@ var hqCmd = async (args, deps) => {
51
51
  return 1;
52
52
  };
53
53
  async function startServer(deps) {
54
- const { startHqServer } = await import("./hq-server-GZGM4BHA.js");
54
+ const { startHqServer } = await import("./hq-server-4MIW3S4J.js");
55
55
  const dataDir = resolveDataDir(deps);
56
56
  const flags = deps.flags ?? {};
57
57
  const host = typeof flags["host"] === "string" ? flags["host"] : HQ_CLI_DEFAULT_HOST;
@@ -709,4 +709,4 @@ export {
709
709
  hqCmd,
710
710
  resolveAuditActor
711
711
  };
712
- //# sourceMappingURL=hq-AG4VW4XO.js.map
712
+ //# sourceMappingURL=hq-3BEUEXJQ.js.map
@@ -15,7 +15,7 @@ import {
15
15
  readLocalSubagentTranscript,
16
16
  sanitizeApiError,
17
17
  startHqServer
18
- } from "./chunk-KQNYSZG2.js";
18
+ } from "./chunk-J3XBHGEO.js";
19
19
  import "./chunk-KE7E7DPX.js";
20
20
  import "./chunk-Q5GTM25S.js";
21
21
  import "./chunk-7OCVIDC7.js";
@@ -37,4 +37,4 @@ export {
37
37
  sanitizeApiError,
38
38
  startHqServer
39
39
  };
40
- //# sourceMappingURL=hq-server-GZGM4BHA.js.map
40
+ //# sourceMappingURL=hq-server-4MIW3S4J.js.map
package/dist/index.js CHANGED
@@ -23,12 +23,12 @@ import {
23
23
  } from "./chunk-52C7PD2H.js";
24
24
  import {
25
25
  runUpdateCommand
26
- } from "./chunk-63GFD62R.js";
26
+ } from "./chunk-4S52MIIM.js";
27
27
  import "./chunk-U3SS4NRH.js";
28
28
  import "./chunk-NUIHRGPY.js";
29
29
  import {
30
30
  DEFAULT_PORT
31
- } from "./chunk-KQNYSZG2.js";
31
+ } from "./chunk-J3XBHGEO.js";
32
32
  import "./chunk-KE7E7DPX.js";
33
33
  import "./chunk-Q5GTM25S.js";
34
34
  import {
@@ -1645,8 +1645,8 @@ var helpTable = {
1645
1645
  update: {
1646
1646
  name: "update",
1647
1647
  title: "wstack update \u2014 self-update the CLI",
1648
- description: "Check the latest npm version and update the globally-installed `wrongstack` package. Use `--check-only` to just print the current/latest without installing. The update is global; run from any project root.",
1649
- usage: "wstack update [--check-only]",
1648
+ description: "Check the latest npm version and update the globally-installed `wrongstack` package. Use `--check-only` to just print the current/latest without installing. Pass `--pm <manager>` (or its shorthand `--npm`, `--pnpm`, `--yarn`, `--bun`) to force a specific package manager; pass `--allow-scripts` (alias `--lifecycle-scripts`) to opt into package lifecycle scripts during the update (off by default). The update is global; run from any project root.",
1649
+ usage: "wstack update [--check-only] [--pm <manager>] [--allow-scripts (alias: --lifecycle-scripts)]",
1650
1650
  seeAlso: "wstack version (read-only version info)"
1651
1651
  },
1652
1652
  // -- ACP (Agent Client Protocol) --------------------------------------
@@ -1861,10 +1861,10 @@ var subcommandsWithFocusedHelp = Object.keys(helpTable);
1861
1861
 
1862
1862
  // src/subcommands/index.ts
1863
1863
  var loaders = {
1864
- acp: async () => (await import("./acp-EA57GUFB.js")).acpCmd,
1864
+ acp: async () => (await import("./acp-GZIASCLH.js")).acpCmd,
1865
1865
  init: async () => (await import("./init-4JQSG66Q.js")).initCmd,
1866
1866
  auth: async () => (await import("./auth-VQMSZGKE.js")).authCmd,
1867
- update: async () => (await import("./update-RATFF63M.js")).updateCmd,
1867
+ update: async () => (await import("./update-ZXNC6I6G.js")).updateCmd,
1868
1868
  sessions: async () => (await import("./sessions-config-7Q7QJBKJ.js")).sessionsCmd,
1869
1869
  config: async () => (await import("./sessions-config-7Q7QJBKJ.js")).configCmd,
1870
1870
  rewind: async () => (await import("./rewind-2FFNOOKS.js")).rewindCmd,
@@ -1877,8 +1877,9 @@ var loaders = {
1877
1877
  mcp: async () => (await import("./mcp-RRPKNRSN.js")).mcpCmd,
1878
1878
  plugin: async () => (await import("./plugin-usage-GCTYOZPH.js")).pluginCmd,
1879
1879
  plugins: async () => (await import("./plugin-usage-GCTYOZPH.js")).pluginCmd,
1880
- diag: async () => (await import("./diag-doctor-HJKFUY6B.js")).diagCmd,
1881
- doctor: async () => (await import("./diag-doctor-HJKFUY6B.js")).doctorCmd,
1880
+ diag: async () => (await import("./diag-doctor-Z6JDXBVX.js")).diagCmd,
1881
+ doctor: async () => (await import("./diag-doctor-Z6JDXBVX.js")).doctorCmd,
1882
+ "proxy-status": async () => (await import("./diag-doctor-Z6JDXBVX.js")).proxyCmd,
1882
1883
  export: async () => (await import("./export-ROG3DKTZ.js")).exportCmd,
1883
1884
  usage: async () => (await import("./plugin-usage-GCTYOZPH.js")).usageCmd,
1884
1885
  version: async () => (await import("./version-help-WMPSEL4U.js")).versionCmd,
@@ -1888,7 +1889,7 @@ var loaders = {
1888
1889
  quick: async () => (await import("./quick-XLYLZX4B.js")).quickCmd,
1889
1890
  bench: async () => (await import("./bench-XYG56AMO.js")).benchCmd,
1890
1891
  chronicle: async () => (await import("./chronicle-6EPPMUC5.js")).chronicleCmd,
1891
- hq: async () => (await import("./hq-AG4VW4XO.js")).hqCmd,
1892
+ hq: async () => (await import("./hq-3BEUEXJQ.js")).hqCmd,
1892
1893
  mailbox: async () => (await import("./mailbox-serve-5S3PHG5D.js")).mailboxServeCmd,
1893
1894
  permissions: async () => (await import("./permissions-2PWBL4YU.js")).permissionsCmd,
1894
1895
  project: async () => (await import("./project-BLQ3ALVL.js")).projectCmd,
@@ -1967,7 +1968,7 @@ async function isPortInUse(host, port) {
1967
1968
  }
1968
1969
  async function handleHqShortCircuit(flags) {
1969
1970
  if (flags["hq"] !== true) return null;
1970
- const { startHqServer } = await import("./hq-server-GZGM4BHA.js");
1971
+ const { startHqServer } = await import("./hq-server-4MIW3S4J.js");
1971
1972
  const tunnelRequested = flags["tunnel"] === true;
1972
1973
  const host = typeof flags["host"] === "string" ? flags["host"] : tunnelRequested ? "127.0.0.1" : HQ_CLI_DEFAULT_HOST2;
1973
1974
  if (tunnelRequested && !isLoopbackHost(host)) {
@@ -4480,7 +4481,7 @@ async function initializeCli(argv) {
4480
4481
  async function main(argv) {
4481
4482
  const cliCtx = await initializeCli(argv);
4482
4483
  if (typeof cliCtx === "number") return cliCtx;
4483
- const { runInteractive } = await import("./cli-main-RFEZAJ4U.js");
4484
+ const { runInteractive } = await import("./cli-main-UDWMWX55.js");
4484
4485
  return runInteractive(cliCtx);
4485
4486
  }
4486
4487
 
@@ -88,5 +88,19 @@ export interface LiveSettingsInput {
88
88
  nextStepsTool?: boolean | undefined;
89
89
  /** Minimum relation strength for SAGE memory injection. Default: 0.85. */
90
90
  sageMemoryInjectThreshold?: number | undefined;
91
+ /**
92
+ * WrongProxy / WrongTrace: master switch. When true AND the daemon at
93
+ * `wrongProxyUrl` is reachable, every provider's base URL is rewritten
94
+ * through `${wrongProxyUrl}/proxy/<host><path>`. openai-codex is
95
+ * excluded by spec. Persisted to `tools.wrongProxy.enabled` (read at
96
+ * boot, applied mid-session by `applyLiveSettings`).
97
+ */
98
+ wrongProxyEnabled?: boolean | undefined;
99
+ /**
100
+ * WrongProxy / WrongTrace URL. Default `http://localhost:8000`. The
101
+ * CLI's periodic probe targets `<wrongProxyUrl>/api/health`; a 2xx
102
+ * response flips the runtime's `active` flag.
103
+ */
104
+ wrongProxyUrl?: string | undefined;
91
105
  }
92
106
  //# sourceMappingURL=live-settings-input.d.ts.map
@@ -0,0 +1,15 @@
1
+ import {
2
+ applyWrongProxyPrefs,
3
+ awaitFirstWrongProxyProbe,
4
+ bootstrapWrongProxy,
5
+ shutdownWrongProxy
6
+ } from "./chunk-3FHFGIIN.js";
7
+ import "./chunk-3MAUU765.js";
8
+ import "./chunk-7OCVIDC7.js";
9
+ export {
10
+ applyWrongProxyPrefs,
11
+ awaitFirstWrongProxyProbe,
12
+ bootstrapWrongProxy,
13
+ shutdownWrongProxy
14
+ };
15
+ //# sourceMappingURL=proxy-wiring-7RPGBHZP.js.map
@@ -1,4 +1,18 @@
1
1
  import type { SubcommandHandler } from '../contracts.js';
2
2
  export declare const diagCmd: SubcommandHandler;
3
+ /**
4
+ * `wstack proxy-status` — print the live in-process `ProxyConfig` singleton.
5
+ *
6
+ * A fresh `wstack` invocation has never booted the WS prefs pipeline that
7
+ * the long-running session uses to populate the singleton, so reading
8
+ * `getProxyConfig()` raw here would always return the module default
9
+ * (`enabled=false, url='', active=false`) regardless of what's on disk
10
+ * or whether the daemon is reachable. To answer "did the probe flip
11
+ * active=true?" we seed the singleton from persisted prefs (`config.tools
12
+ * .wrongProxy`), start a one-shot probe, await its first poke, and only
13
+ * then read state. `startProxyProbe()` is idempotent so this is safe to
14
+ * call from a subcommand that has no other runtime side-effects.
15
+ */
16
+ export declare const proxyCmd: SubcommandHandler;
3
17
  export declare const doctorCmd: SubcommandHandler;
4
18
  //# sourceMappingURL=diag-doctor.d.ts.map
@@ -3,7 +3,7 @@ import {
3
3
  detectUpdatePackageName,
4
4
  runUpdateCommand,
5
5
  updateCmd
6
- } from "./chunk-63GFD62R.js";
6
+ } from "./chunk-4S52MIIM.js";
7
7
  import "./chunk-U3SS4NRH.js";
8
8
  import "./chunk-NUIHRGPY.js";
9
9
  import "./chunk-7OCVIDC7.js";
@@ -13,4 +13,4 @@ export {
13
13
  runUpdateCommand,
14
14
  updateCmd
15
15
  };
16
- //# sourceMappingURL=update-RATFF63M.js.map
16
+ //# sourceMappingURL=update-ZXNC6I6G.js.map
@@ -18,6 +18,10 @@ interface CliWebUIOptions {
18
18
  fallbackAuto?: boolean | undefined;
19
19
  modelMatrix?: Config['modelMatrix'] | undefined;
20
20
  uiLocale?: string | undefined;
21
+ /** WrongProxy / WrongTrace toggle. */
22
+ wrongProxyEnabled?: boolean | undefined;
23
+ /** WrongProxy / WrongTrace URL. Default: 'http://localhost:8000'. */
24
+ wrongProxyUrl?: string | undefined;
21
25
  } | undefined;
22
26
  }
23
27
  type PrefSnapshot = Record<string, unknown>;
@@ -746,6 +746,12 @@ function createPrefsSeeding(opts) {
746
746
  if (typeof payload["uiLocale"] === "string") {
747
747
  patchLiveAppConfig({ uiLocale: payload["uiLocale"] });
748
748
  }
749
+ if (typeof payload["wrongProxyEnabled"] === "boolean") {
750
+ patchLiveAppConfig({ wrongProxyEnabled: payload["wrongProxyEnabled"] });
751
+ }
752
+ if (typeof payload["wrongProxyUrl"] === "string") {
753
+ patchLiveAppConfig({ wrongProxyUrl: payload["wrongProxyUrl"] });
754
+ }
749
755
  if (payload["modelMatrix"] && typeof payload["modelMatrix"] === "object" && !Array.isArray(payload["modelMatrix"])) {
750
756
  patchLiveAppConfig({ modelMatrix: payload["modelMatrix"] });
751
757
  }
@@ -881,6 +887,7 @@ function createWebuiRouteContexts({
881
887
  persist: persistPrefs,
882
888
  setYolo: opts.onYoloSwitch,
883
889
  setAutonomy: opts.onAutonomySwitch,
890
+ applyWrongProxyPrefs: opts.onWrongProxyPrefsChange,
884
891
  pendingConfirms,
885
892
  configStore: opts.agent.container?.safeResolve?.(TOKENS2.ConfigStore),
886
893
  send,
@@ -1686,4 +1693,4 @@ async function runWebUI(opts) {
1686
1693
  export {
1687
1694
  runWebUI
1688
1695
  };
1689
- //# sourceMappingURL=webui-server-3DU6BVTB.js.map
1696
+ //# sourceMappingURL=webui-server-UB75UHWX.js.map
@@ -205,6 +205,14 @@ export interface CliWebUIOptions {
205
205
  onAutonomySwitch?: ((mode: string) => void) | undefined;
206
206
  /** Forward browser YOLO changes to the host's live permission policy. */
207
207
  onYoloSwitch?: ((enabled: boolean) => void) | undefined;
208
+ /**
209
+ * Forward `wrongProxyEnabled` / `wrongProxyUrl` changes from the
210
+ * browser to the runtime probe (`@wrongstack/cli/wiring/proxy-wiring`).
211
+ * Mirrors the `onAutonomySwitch` / `onYoloSwitch` pattern: the WS
212
+ * server stays package-agnostic and the boot site provides the
213
+ * host-side effect.
214
+ */
215
+ onWrongProxyPrefsChange?: ((payload: Record<string, unknown>) => void) | undefined;
208
216
  /**
209
217
  * Pre-computed update info from the CLI's preflight version check.
210
218
  * When present, the session.start payload includes appVersion,
@@ -42,6 +42,31 @@ export interface ResolvedProviderCfg {
42
42
  factoryType: string;
43
43
  }
44
44
  export declare function resolveProviderCfg(config: Pick<Config, 'providers' | 'apiKey' | 'baseUrl'>, providerId: string): ResolvedProviderCfg;
45
+ /**
46
+ * Shared proxy-aware provider-config resolver.
47
+ *
48
+ * Three sites in this monorepo merge a saved provider config with the
49
+ * top-level Config and hand the result to a provider factory:
50
+ *
51
+ * 1. `packages/cli/src/wiring/provider-runtime.ts` `resolveProviderCfg()`
52
+ * — used by `/model`, the fallback extension, and any other runtime
53
+ * path that rebuilds a Provider from a saved-config alias.
54
+ * 2. `packages/cli/src/wiring/provider.ts` `setupProvider()` — the
55
+ * boot-time setup path for the active session provider.
56
+ * 3. `packages/runtime/src/fleet/light-subagent-factory.ts` `buildProvider()`
57
+ * — subagent provider construction for SDD runs.
58
+ *
59
+ * Each of those had to apply the same proxy rewrite. The duplication
60
+ * drifted: `provider.ts:154` was force-setting `type: config.provider`
61
+ * before the `factoryType` read at line 158, silently destroying any
62
+ * saved-alias `type` field (e.g. `minimax-coding-plan` mapped to
63
+ * `type: 'anthropic'`). The drift was caught by Chimera review; this
64
+ * helper is the single source of truth that prevents it from recurring.
65
+ *
66
+ * Inputs are intentionally `Pick<Config, ...>` (not the full Config) so
67
+ * this helper stays free of disk I/O and can be called from any layer.
68
+ */
69
+ export declare function resolveProviderCfgWithProxy(config: Pick<Config, 'providers' | 'apiKey' | 'baseUrl'>, providerId: string): ResolvedProviderCfg;
45
70
  /**
46
71
  * Construct a credential-resolved Provider for a provider id, WITHOUT
47
72
  * persisting anything. Shared by the `/model` switch and the fallback
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Periodic health probe for the local WrongProxy / WrongTrace daemon.
3
+ *
4
+ * The daemon exposes `GET <base>/api/health` returning JSON like:
5
+ * { "repo": "WrongTrace", "status": "ok", "timestamp": "...", ... }
6
+ *
7
+ * The probe:
8
+ * 1. Runs once on boot so the first request doesn't hit a dead proxy.
9
+ * 2. Re-runs every `intervalMs` (default 30s) while the toggle is on.
10
+ * 3. Aborts in-flight probes on every state change so we never accumulate
11
+ * a backlog when the user toggles the proxy on/off rapidly.
12
+ * 4. Uses a small per-call AbortController + timeout (2s) so a hung
13
+ * `localhost:8000` cannot stall the loop.
14
+ *
15
+ * The probe is intentionally minimal: the daemon's `/api/health` response
16
+ * shape is small and stable, so we don't try to parse it — a 2xx is
17
+ * enough to mark the proxy active. Failures (timeout, non-2xx, ECONNREFUSED)
18
+ * are treated as SOFT signals: a single transient failure (daemon mid-
19
+ * restart, one dropped 2xx) must not flip `active` to false and silently
20
+ * disable rewrites for every subsequent request. `active` flips to false
21
+ * only after `deactivateAfterFailures` consecutive failures; the periodic
22
+ * loop keeps retrying, so a recovered daemon re-activates on the next
23
+ * successful probe. Toggle-off (`enabled: false` / no URL) still deactivates
24
+ * immediately.
25
+ */
26
+ interface ProbeRunnerOptions {
27
+ /** Override the default interval (30s). Useful for tests. */
28
+ intervalMs?: number;
29
+ /** Override the default per-request timeout (2s). Useful for tests. */
30
+ timeoutMs?: number;
31
+ /** Override `fetch` for tests. */
32
+ fetchImpl?: typeof fetch;
33
+ /** Override `setInterval` / `clearInterval` for tests. */
34
+ setIntervalImpl?: typeof setInterval;
35
+ clearIntervalImpl?: typeof clearInterval;
36
+ /**
37
+ * Number of CONSECUTIVE failed probes required before `active` flips to
38
+ * false. A single transient failure is a soft signal and leaves `active`
39
+ * untouched. Defaults to 2. Useful for tests wanting to exercise the
40
+ * threshold without waiting two ticks.
41
+ */
42
+ deactivateAfterFailures?: number;
43
+ }
44
+ export interface ProbeRunner {
45
+ /** Stop the periodic probe and abort any in-flight request. */
46
+ stop(): void;
47
+ /** Force an immediate probe (next tick). Resolves with whether the health check succeeded. */
48
+ poke(): Promise<boolean>;
49
+ }
50
+ /**
51
+ * Start the probe loop. Idempotent — repeated calls reuse the existing
52
+ * runner unless `stop()` was called in between.
53
+ */
54
+ export declare function startProxyProbe(opts?: ProbeRunnerOptions): ProbeRunner;
55
+ /**
56
+ * Stop any running probe. Safe to call when nothing is running.
57
+ */
58
+ export declare function stopProxyProbe(): void;
59
+ /** Test-only: clear module state without touching timers. */
60
+ export declare function __resetProxyProbeForTests(): void;
61
+ export {};
62
+ //# sourceMappingURL=proxy-probe.d.ts.map
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Bridge between the WS prefs pipeline and the proxy-rewrite runtime.
3
+ *
4
+ * Lives in `@wrongstack/cli/wiring/proxy-wiring.ts` because it owns the
5
+ * side-effectful boot of the probe loop — `proxy-rewrite` is pure logic
6
+ * and `proxy-probe` is the periodic side-effect loop, but neither knows
7
+ * about WS prefs. This module is the single owner of:
8
+ *
9
+ * - the singleton probe runner
10
+ * - pushing user prefs into the proxy-rewrite config
11
+ * - kicking off the periodic /api/health probe when the toggle goes on
12
+ *
13
+ * Re-exported so `handlePrefsUpdate` in `@wrongstack/webui-server` can
14
+ * call `applyWrongProxyPrefs(payload)` without taking a direct dependency
15
+ * on `proxy-probe` (the WS server is intentionally provider-agnostic).
16
+ */
17
+ /**
18
+ * Apply the `wrongProxyEnabled` + `wrongProxyUrl` portion of a prefs
19
+ * payload. Idempotent — safe to call on every `prefs.update`. Boots the
20
+ * probe on first call so the rewrite can be marked active before the
21
+ * next request hits the provider factory.
22
+ */
23
+ export declare function applyWrongProxyPrefs(payload: Record<string, unknown>): void;
24
+ /**
25
+ * Await one probe pass so the `ProxyConfig` singleton's `active` flag is
26
+ * settled before the caller reads it. Returns immediately when no probe
27
+ * runner exists (toggle never enabled). Each call triggers a fresh
28
+ * `runOnce()` probe — there is no memoization — so call it once per
29
+ * decision point, not per request.
30
+ *
31
+ * This closes the cli-main boot race: `bootstrapWrongProxy()` seeds
32
+ * `enabled` / `url` synchronously, but `startProxyProbe()` only schedules
33
+ * a 30 s `setInterval` and the first `poke()` resolves on the next
34
+ * macrotask. `setupProviderRuntime()` runs synchronously on the very
35
+ * next line, so without this gate providers are constructed with the raw
36
+ * base URL even when the toggle is on.
37
+ */
38
+ export declare function awaitFirstWrongProxyProbe(): Promise<void>;
39
+ /**
40
+ * Apply the initial prefs snapshot at boot. Same as `applyWrongProxyPrefs`
41
+ * but explicitly named for the boot site so future readers can find it.
42
+ *
43
+ * Accepts the canonical persisted shape (`config.tools.wrongProxy` —
44
+ * `{ enabled?, url? }`) directly. The `enabled` / `url` keys are mapped
45
+ * to the flat `wrongProxyEnabled` / `wrongProxyUrl` keys the proxy
46
+ * rewriter reads; any other keys in the snapshot are ignored. Callers
47
+ * that hold a `WrongProxyToolConfig` (the typed schema in
48
+ * `@wrongstack/core/types/config/tools.ts`) can pass it through without
49
+ * casting — the function never reads anything beyond `enabled` / `url`.
50
+ */
51
+ export declare function bootstrapWrongProxy(snapshot: {
52
+ enabled?: boolean | undefined;
53
+ url?: string | undefined;
54
+ } | Record<string, unknown> | undefined): void;
55
+ /**
56
+ * Stop the probe. Intended for graceful shutdown / test cleanup.
57
+ */
58
+ export declare function shutdownWrongProxy(): void;
59
+ //# sourceMappingURL=proxy-wiring.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/cli",
3
- "version": "0.310.0",
3
+ "version": "0.310.1",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack CLI — terminal AI coding agent with provider catalog from models.dev. Provides `wrongstack` and `wstack` binaries.",
6
6
  "keywords": [
@@ -42,34 +42,34 @@
42
42
  ],
43
43
  "dependencies": {
44
44
  "ws": "^8.21.3",
45
- "@wrongstack/acp": "0.310.0",
46
- "@wrongstack/bench": "0.310.0",
47
- "@wrongstack/core": "0.310.0",
48
- "@wrongstack/persistence": "0.310.0",
49
- "@wrongstack/kanban": "0.310.0",
50
- "@wrongstack/plugins": "0.310.0",
51
- "@wrongstack/plug-lsp": "0.310.0",
52
- "@wrongstack/primitives": "0.310.0",
53
- "@wrongstack/providers": "0.310.0",
54
- "@wrongstack/runtime": "0.310.0",
55
- "@wrongstack/sdd": "0.310.0",
56
- "@wrongstack/mcp": "0.310.0",
57
- "@wrongstack/requirement-intake": "0.310.0",
58
- "@wrongstack/sage": "0.310.0",
59
- "@wrongstack/security-scanner": "0.310.0",
60
- "@wrongstack/techstack": "0.310.0",
61
- "@wrongstack/telegram": "0.310.0",
62
- "@wrongstack/simpleui": "0.310.0",
63
- "@wrongstack/vector-memory": "0.310.0",
64
- "@wrongstack/tools": "0.310.0",
65
- "@wrongstack/webui": "0.310.0",
66
- "@wrongstack/webui-server": "0.310.0",
67
- "@wrongstack/webui-hq": "0.310.0",
68
- "@wrongstack/tui": "0.310.0",
69
- "@wrongstack/webui-protocol": "0.310.0"
45
+ "@wrongstack/core": "0.310.1",
46
+ "@wrongstack/acp": "0.310.1",
47
+ "@wrongstack/bench": "0.310.1",
48
+ "@wrongstack/mcp": "0.310.1",
49
+ "@wrongstack/primitives": "0.310.1",
50
+ "@wrongstack/plug-lsp": "0.310.1",
51
+ "@wrongstack/persistence": "0.310.1",
52
+ "@wrongstack/kanban": "0.310.1",
53
+ "@wrongstack/runtime": "0.310.1",
54
+ "@wrongstack/requirement-intake": "0.310.1",
55
+ "@wrongstack/sage": "0.310.1",
56
+ "@wrongstack/sdd": "0.310.1",
57
+ "@wrongstack/simpleui": "0.310.1",
58
+ "@wrongstack/tools": "0.310.1",
59
+ "@wrongstack/security-scanner": "0.310.1",
60
+ "@wrongstack/telegram": "0.310.1",
61
+ "@wrongstack/vector-memory": "0.310.1",
62
+ "@wrongstack/providers": "0.310.1",
63
+ "@wrongstack/webui": "0.310.1",
64
+ "@wrongstack/plugins": "0.310.1",
65
+ "@wrongstack/webui-hq": "0.310.1",
66
+ "@wrongstack/techstack": "0.310.1",
67
+ "@wrongstack/webui-protocol": "0.310.1",
68
+ "@wrongstack/tui": "0.310.1",
69
+ "@wrongstack/webui-server": "0.310.1"
70
70
  },
71
71
  "optionalDependencies": {
72
- "@wrongstack/desktop": "0.310.0"
72
+ "@wrongstack/desktop": "0.310.1"
73
73
  },
74
74
  "devDependencies": {
75
75
  "@types/node": "^26.2.0",