@wrongstack/webui-server 0.310.1 → 0.313.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.
package/dist/index.js CHANGED
@@ -100,7 +100,7 @@ var BOOLEAN_PREF_KEYS = /* @__PURE__ */ new Set([
100
100
  "showSageMemoryInject",
101
101
  // WrongProxy / WrongTrace master switch. When on, the CLI rewrites every
102
102
  // provider's base URL through the configured proxy URL (default
103
- // http://localhost:8000 → http://localhost:8000/proxy/<host><path>).
103
+ // http://localhost:3444 → http://localhost:3444/proxy/<host><path>).
104
104
  // Excluded providers (openai-codex) flow through unchanged.
105
105
  "wrongProxyEnabled"
106
106
  ]);
@@ -171,7 +171,7 @@ var STRING_PREF_KEYS = /* @__PURE__ */ new Set([
171
171
  "autoReviewModel",
172
172
  "autoReviewFallbackProfile",
173
173
  // WrongProxy / WrongTrace URL. Empty = unset. Default lives in
174
- // `LocalPrefs.DEFAULTS.wrongProxyUrl` ('http://localhost:8000'); users
174
+ // `LocalPrefs.DEFAULTS.wrongProxyUrl` ('http://localhost:3444'); users
175
175
  // can override here for non-default daemon ports / paths.
176
176
  "wrongProxyUrl"
177
177
  ]);
@@ -187,7 +187,7 @@ var ENUM_PREF_KEYS = {
187
187
  reasoningEffort: REASONING_EFFORT_VALUES,
188
188
  cacheTtl: CACHE_TTL_VALUES,
189
189
  statuslineMode: /* @__PURE__ */ new Set(["minimum", "detailed", "no-color"]),
190
- animationStyle: /* @__PURE__ */ new Set(["rainbow", "wave", "pulse", "dots", "breathe", "cycle"]),
190
+ animationStyle: /* @__PURE__ */ new Set(["rainbow", "wave", "pulse", "dots", "breathe", "static", "cycle"]),
191
191
  fsAccess: /* @__PURE__ */ new Set(["unrestricted", "project"]),
192
192
  // Chimera autoFix + auto-review cascade threshold
193
193
  chimeraAutoFix: /* @__PURE__ */ new Set(["off", "ask", "auto"]),
@@ -6376,7 +6376,8 @@ function estimateTokens(s) {
6376
6376
  function stringifyContent(c) {
6377
6377
  if (typeof c === "string") return c;
6378
6378
  try {
6379
- return JSON.stringify(c);
6379
+ const serialized = JSON.stringify(c);
6380
+ return serialized === void 0 ? String(c) : serialized;
6380
6381
  } catch {
6381
6382
  return String(c);
6382
6383
  }
@@ -21211,7 +21212,7 @@ var PREF_KEYS = [
21211
21212
  // Fleet chat verbosity: off | full (migrated from streamFleet boolean).
21212
21213
  "fleetChatVerbosity",
21213
21214
  // WrongProxy / WrongTrace: master switch + configurable URL (default
21214
- // http://localhost:8000). When `wrongProxyEnabled` is true and the daemon
21215
+ // http://localhost:3444). When `wrongProxyEnabled` is true and the daemon
21215
21216
  // is reachable, every provider's base URL flows through
21216
21217
  // `${wrongProxyUrl}/proxy/<host><path>`. openai-codex is excluded by spec.
21217
21218
  "wrongProxyEnabled",
@@ -23919,6 +23920,17 @@ function setupEvents(deps2) {
23919
23920
  })
23920
23921
  });
23921
23922
  });
23923
+ on("provider.model_switched", (e) => {
23924
+ broadcast2(clients, {
23925
+ type: "provider.model_switched",
23926
+ payload: sessionPayload2({
23927
+ sessionId: e.sessionId,
23928
+ from: e.from,
23929
+ to: e.to,
23930
+ timestamp: e.timestamp
23931
+ })
23932
+ });
23933
+ });
23922
23934
  on("provider.fallback_pending", (e) => {
23923
23935
  broadcast2(clients, {
23924
23936
  type: "provider.fallback_pending",
@@ -24257,6 +24269,8 @@ import {
24257
24269
  // src/server/backend-services.ts
24258
24270
  import { join as join15 } from "node:path";
24259
24271
  import { Agent } from "@wrongstack/core/agent";
24272
+ import { HookRegistry, HookRunner } from "@wrongstack/core/hooks";
24273
+ import { createWrongTraceHookPair, recordGateDecision, snapshotGateDecisions, persistWrongTraceGateCounters } from "@wrongstack/wrongtrace";
24260
24274
  import {
24261
24275
  BrainDecisionLedger,
24262
24276
  BrainMonitor,
@@ -25298,6 +25312,33 @@ async function createAgentServices(input) {
25298
25312
  const secretScrubber = container.resolve(TOKENS2.SecretScrubber);
25299
25313
  const renderer = container.has(TOKENS2.Renderer) ? container.resolve(TOKENS2.Renderer) : void 0;
25300
25314
  const permissionPolicy = container.resolve(TOKENS2.PermissionPolicy);
25315
+ const wrongTraceHookRegistry = new HookRegistry();
25316
+ const wrongTraceHooks = createWrongTraceHookPair(() => context.session.id, {
25317
+ emit: (event) => {
25318
+ events.emit("wrongtrace.gate.decision", event);
25319
+ recordGateDecision(event);
25320
+ void persistWrongTraceGateCounters(projectRoot, snapshotGateDecisions());
25321
+ }
25322
+ });
25323
+ wrongTraceHookRegistry.registerInProcess(
25324
+ "PreToolUse",
25325
+ "edit|write|replace|patch|codebase-ast-replace",
25326
+ wrongTraceHooks.preToolUse,
25327
+ "wrongtrace-gate"
25328
+ );
25329
+ wrongTraceHookRegistry.registerInProcess(
25330
+ "PostToolUse",
25331
+ "edit|write|replace|patch|codebase-ast-replace",
25332
+ wrongTraceHooks.postToolUse,
25333
+ "wrongtrace-gate"
25334
+ );
25335
+ const wrongTraceHookRunner = new HookRunner({
25336
+ registry: wrongTraceHookRegistry,
25337
+ sessionId: () => context.session.id,
25338
+ // Coordination, not enforcement: these hooks are fail-open by
25339
+ // construction and must run regardless of shell-hook gating.
25340
+ allowNonPolicy: true
25341
+ });
25301
25342
  const toolExecutor = new ToolExecutor(toolRegistry, {
25302
25343
  permissionPolicy,
25303
25344
  secretScrubber,
@@ -25307,6 +25348,7 @@ async function createAgentServices(input) {
25307
25348
  iterationTimeoutMs: config.tools?.iterationTimeoutMs ?? DEFAULT_TOOLS_CONFIG.iterationTimeoutMs,
25308
25349
  perIterationOutputCapBytes: config.tools?.perIterationOutputCapBytes ?? DEFAULT_TOOLS_CONFIG.perIterationOutputCapBytes,
25309
25350
  tracer: void 0,
25351
+ hookRunner: wrongTraceHookRunner,
25310
25352
  // Off unless the operator opts in. The WebUI drives the same agent as the
25311
25353
  // CLI, so it must resolve this identically — a surface-dependent gate
25312
25354
  // would mean the same repo governs under `wstack` and not in the browser.
@@ -25528,6 +25570,12 @@ async function createAgentServices(input) {
25528
25570
  // round-robin keeps reassigning the doomed model. Mirrors the CLI
25529
25571
  // factory wiring at host-subagent-factory.ts:337.
25530
25572
  statusTracker: container.safeResolve(TOKENS2.ProviderModelStatusTracker),
25573
+ // WrongTrace lock gate for SDD-wizard workers: the standalone server
25574
+ // already built a dedicated WrongTrace-only HookRunner for its own
25575
+ // executor above; handing the same runner to the runtime factory
25576
+ // makes every worker edit honor peer locks with one process-wide
25577
+ // owner identity (context.session.id).
25578
+ hookRunner: wrongTraceHookRunner,
25531
25579
  ...input.installToolBoundary ? { installToolBoundary: input.installToolBoundary } : {}
25532
25580
  }),
25533
25581
  paths: {
@@ -27597,6 +27645,40 @@ function setupWebuiCredentialWatcher(options) {
27597
27645
  return credentialWatcher.close;
27598
27646
  }
27599
27647
 
27648
+ // src/server/start-webui-proxy-apply.ts
27649
+ import { createProxyInstantApply } from "@wrongstack/core/wiring/proxy-rewrite";
27650
+ import { makeProviderFromConfig as makeProviderFromConfig6, withCatalogCapabilities as withCatalogCapabilities2 } from "@wrongstack/providers";
27651
+ function setupWebuiProxyInstantApply(options) {
27652
+ const { state, deps: deps2, updateAutoCompactionMaxContext } = options;
27653
+ const instantApply = createProxyInstantApply({
27654
+ // Prefer the LIVE provider id over the config's — mirrors the CLI
27655
+ // wiring; the context is the source of truth once the session boots.
27656
+ getActiveProviderId: () => deps2.context.provider?.id ?? state.getConfig().provider ?? "",
27657
+ // Same raw-read rule as every other WebUI provider-build site:
27658
+ // savedCfg.baseUrl ?? top-level config.baseUrl.
27659
+ getRawBaseUrl: (providerId) => state.getConfig().providers?.[providerId]?.baseUrl ?? state.getConfig().baseUrl,
27660
+ rebuildProvider: async (providerId) => {
27661
+ await deps2.context.runModelTransition(async () => {
27662
+ if (deps2.context.provider?.id !== providerId) return;
27663
+ const cur = state.getConfig();
27664
+ const providerCfg = cur.providers?.[providerId] ?? { type: providerId };
27665
+ const routedCfg = routeProviderCfgThroughProxy(providerCfg, cur.baseUrl, providerId);
27666
+ const built = deps2.providerRegistry.has(providerId) ? deps2.providerRegistry.create({ ...routedCfg, type: providerId }) : makeProviderFromConfig6(providerId, routedCfg);
27667
+ const model = deps2.context.model ?? cur.model ?? "";
27668
+ const newProv = deps2.modelsRegistry ? await withCatalogCapabilities2(deps2.modelsRegistry, providerId, built, {
27669
+ ...routedCfg,
27670
+ type: providerId,
27671
+ model
27672
+ }) : built;
27673
+ deps2.context.provider = newProv;
27674
+ void updateAutoCompactionMaxContext(newProv, providerId).catch(() => void 0);
27675
+ });
27676
+ },
27677
+ logger: deps2.logger
27678
+ });
27679
+ return () => instantApply.dispose();
27680
+ }
27681
+
27600
27682
  // src/server/start-webui-remediation.ts
27601
27683
  import { randomUUID as randomUUID5 } from "node:crypto";
27602
27684
  import { toLanguagePackageInput } from "@wrongstack/techstack";
@@ -27686,6 +27768,7 @@ function setupWebuiShutdown(options) {
27686
27768
  await options.todosCheckpoint.detach();
27687
27769
  await options.stopHeapWatchdog();
27688
27770
  options.getCredentialWatcherClose()?.();
27771
+ options.getProxyInstantApplyDispose()();
27689
27772
  options.disposeRealtimeHandlers();
27690
27773
  const governanceCleanup = await options.governanceHandle?.close();
27691
27774
  if (governanceCleanup && !governanceCleanup.ok) {
@@ -28232,6 +28315,11 @@ async function startWebUI(opts = {}) {
28232
28315
  clients,
28233
28316
  updateAutoCompactionMaxContext
28234
28317
  });
28318
+ const proxyInstantApplyDispose = setupWebuiProxyInstantApply({
28319
+ state,
28320
+ deps: deps2,
28321
+ updateAutoCompactionMaxContext
28322
+ });
28235
28323
  const stopHeapWatchdog = startSharedHeapWatchdog({
28236
28324
  collectStats: () => ({
28237
28325
  surface: opts.surface ?? "webui",
@@ -28339,6 +28427,7 @@ projectRoot: ${ev.projectRoot ?? "?"}`,
28339
28427
  todosCheckpoint,
28340
28428
  stopHeapWatchdog,
28341
28429
  getCredentialWatcherClose: () => credentialWatcherClose,
28430
+ getProxyInstantApplyDispose: () => proxyInstantApplyDispose,
28342
28431
  disposeRealtimeHandlers,
28343
28432
  governanceHandle,
28344
28433
  logger,
@@ -101,7 +101,7 @@ var BOOLEAN_PREF_KEYS = /* @__PURE__ */ new Set([
101
101
  "showSageMemoryInject",
102
102
  // WrongProxy / WrongTrace master switch. When on, the CLI rewrites every
103
103
  // provider's base URL through the configured proxy URL (default
104
- // http://localhost:8000 → http://localhost:8000/proxy/<host><path>).
104
+ // http://localhost:3444 → http://localhost:3444/proxy/<host><path>).
105
105
  // Excluded providers (openai-codex) flow through unchanged.
106
106
  "wrongProxyEnabled"
107
107
  ]);
@@ -172,7 +172,7 @@ var STRING_PREF_KEYS = /* @__PURE__ */ new Set([
172
172
  "autoReviewModel",
173
173
  "autoReviewFallbackProfile",
174
174
  // WrongProxy / WrongTrace URL. Empty = unset. Default lives in
175
- // `LocalPrefs.DEFAULTS.wrongProxyUrl` ('http://localhost:8000'); users
175
+ // `LocalPrefs.DEFAULTS.wrongProxyUrl` ('http://localhost:3444'); users
176
176
  // can override here for non-default daemon ports / paths.
177
177
  "wrongProxyUrl"
178
178
  ]);
@@ -188,7 +188,7 @@ var ENUM_PREF_KEYS = {
188
188
  reasoningEffort: REASONING_EFFORT_VALUES,
189
189
  cacheTtl: CACHE_TTL_VALUES,
190
190
  statuslineMode: /* @__PURE__ */ new Set(["minimum", "detailed", "no-color"]),
191
- animationStyle: /* @__PURE__ */ new Set(["rainbow", "wave", "pulse", "dots", "breathe", "cycle"]),
191
+ animationStyle: /* @__PURE__ */ new Set(["rainbow", "wave", "pulse", "dots", "breathe", "static", "cycle"]),
192
192
  fsAccess: /* @__PURE__ */ new Set(["unrestricted", "project"]),
193
193
  // Chimera autoFix + auto-review cascade threshold
194
194
  chimeraAutoFix: /* @__PURE__ */ new Set(["off", "ask", "auto"]),
@@ -6191,7 +6191,8 @@ function estimateTokens(s) {
6191
6191
  function stringifyContent(c) {
6192
6192
  if (typeof c === "string") return c;
6193
6193
  try {
6194
- return JSON.stringify(c);
6194
+ const serialized = JSON.stringify(c);
6195
+ return serialized === void 0 ? String(c) : serialized;
6195
6196
  } catch {
6196
6197
  return String(c);
6197
6198
  }
@@ -19497,7 +19498,7 @@ var PREF_KEYS = [
19497
19498
  // Fleet chat verbosity: off | full (migrated from streamFleet boolean).
19498
19499
  "fleetChatVerbosity",
19499
19500
  // WrongProxy / WrongTrace: master switch + configurable URL (default
19500
- // http://localhost:8000). When `wrongProxyEnabled` is true and the daemon
19501
+ // http://localhost:3444). When `wrongProxyEnabled` is true and the daemon
19501
19502
  // is reachable, every provider's base URL flows through
19502
19503
  // `${wrongProxyUrl}/proxy/<host><path>`. openai-codex is excluded by spec.
19503
19504
  "wrongProxyEnabled",
@@ -22103,6 +22104,17 @@ function setupEvents(deps2) {
22103
22104
  })
22104
22105
  });
22105
22106
  });
22107
+ on("provider.model_switched", (e) => {
22108
+ broadcast2(clients, {
22109
+ type: "provider.model_switched",
22110
+ payload: sessionPayload2({
22111
+ sessionId: e.sessionId,
22112
+ from: e.from,
22113
+ to: e.to,
22114
+ timestamp: e.timestamp
22115
+ })
22116
+ });
22117
+ });
22106
22118
  on("provider.fallback_pending", (e) => {
22107
22119
  broadcast2(clients, {
22108
22120
  type: "provider.fallback_pending",
@@ -22441,6 +22453,8 @@ import {
22441
22453
  // src/server/backend-services.ts
22442
22454
  import { join as join12 } from "node:path";
22443
22455
  import { Agent } from "@wrongstack/core/agent";
22456
+ import { HookRegistry, HookRunner } from "@wrongstack/core/hooks";
22457
+ import { createWrongTraceHookPair, recordGateDecision, snapshotGateDecisions, persistWrongTraceGateCounters } from "@wrongstack/wrongtrace";
22444
22458
  import {
22445
22459
  BrainDecisionLedger,
22446
22460
  BrainMonitor,
@@ -23482,6 +23496,33 @@ async function createAgentServices(input) {
23482
23496
  const secretScrubber = container.resolve(TOKENS.SecretScrubber);
23483
23497
  const renderer = container.has(TOKENS.Renderer) ? container.resolve(TOKENS.Renderer) : void 0;
23484
23498
  const permissionPolicy = container.resolve(TOKENS.PermissionPolicy);
23499
+ const wrongTraceHookRegistry = new HookRegistry();
23500
+ const wrongTraceHooks = createWrongTraceHookPair(() => context.session.id, {
23501
+ emit: (event) => {
23502
+ events.emit("wrongtrace.gate.decision", event);
23503
+ recordGateDecision(event);
23504
+ void persistWrongTraceGateCounters(projectRoot, snapshotGateDecisions());
23505
+ }
23506
+ });
23507
+ wrongTraceHookRegistry.registerInProcess(
23508
+ "PreToolUse",
23509
+ "edit|write|replace|patch|codebase-ast-replace",
23510
+ wrongTraceHooks.preToolUse,
23511
+ "wrongtrace-gate"
23512
+ );
23513
+ wrongTraceHookRegistry.registerInProcess(
23514
+ "PostToolUse",
23515
+ "edit|write|replace|patch|codebase-ast-replace",
23516
+ wrongTraceHooks.postToolUse,
23517
+ "wrongtrace-gate"
23518
+ );
23519
+ const wrongTraceHookRunner = new HookRunner({
23520
+ registry: wrongTraceHookRegistry,
23521
+ sessionId: () => context.session.id,
23522
+ // Coordination, not enforcement: these hooks are fail-open by
23523
+ // construction and must run regardless of shell-hook gating.
23524
+ allowNonPolicy: true
23525
+ });
23485
23526
  const toolExecutor = new ToolExecutor(toolRegistry, {
23486
23527
  permissionPolicy,
23487
23528
  secretScrubber,
@@ -23491,6 +23532,7 @@ async function createAgentServices(input) {
23491
23532
  iterationTimeoutMs: config.tools?.iterationTimeoutMs ?? DEFAULT_TOOLS_CONFIG.iterationTimeoutMs,
23492
23533
  perIterationOutputCapBytes: config.tools?.perIterationOutputCapBytes ?? DEFAULT_TOOLS_CONFIG.perIterationOutputCapBytes,
23493
23534
  tracer: void 0,
23535
+ hookRunner: wrongTraceHookRunner,
23494
23536
  // Off unless the operator opts in. The WebUI drives the same agent as the
23495
23537
  // CLI, so it must resolve this identically — a surface-dependent gate
23496
23538
  // would mean the same repo governs under `wstack` and not in the browser.
@@ -23712,6 +23754,12 @@ async function createAgentServices(input) {
23712
23754
  // round-robin keeps reassigning the doomed model. Mirrors the CLI
23713
23755
  // factory wiring at host-subagent-factory.ts:337.
23714
23756
  statusTracker: container.safeResolve(TOKENS.ProviderModelStatusTracker),
23757
+ // WrongTrace lock gate for SDD-wizard workers: the standalone server
23758
+ // already built a dedicated WrongTrace-only HookRunner for its own
23759
+ // executor above; handing the same runner to the runtime factory
23760
+ // makes every worker edit honor peer locks with one process-wide
23761
+ // owner identity (context.session.id).
23762
+ hookRunner: wrongTraceHookRunner,
23715
23763
  ...input.installToolBoundary ? { installToolBoundary: input.installToolBoundary } : {}
23716
23764
  }),
23717
23765
  paths: {
@@ -25781,6 +25829,40 @@ function setupWebuiCredentialWatcher(options) {
25781
25829
  return credentialWatcher.close;
25782
25830
  }
25783
25831
 
25832
+ // src/server/start-webui-proxy-apply.ts
25833
+ import { createProxyInstantApply } from "@wrongstack/core/wiring/proxy-rewrite";
25834
+ import { makeProviderFromConfig as makeProviderFromConfig4, withCatalogCapabilities as withCatalogCapabilities2 } from "@wrongstack/providers";
25835
+ function setupWebuiProxyInstantApply(options) {
25836
+ const { state, deps: deps2, updateAutoCompactionMaxContext } = options;
25837
+ const instantApply = createProxyInstantApply({
25838
+ // Prefer the LIVE provider id over the config's — mirrors the CLI
25839
+ // wiring; the context is the source of truth once the session boots.
25840
+ getActiveProviderId: () => deps2.context.provider?.id ?? state.getConfig().provider ?? "",
25841
+ // Same raw-read rule as every other WebUI provider-build site:
25842
+ // savedCfg.baseUrl ?? top-level config.baseUrl.
25843
+ getRawBaseUrl: (providerId) => state.getConfig().providers?.[providerId]?.baseUrl ?? state.getConfig().baseUrl,
25844
+ rebuildProvider: async (providerId) => {
25845
+ await deps2.context.runModelTransition(async () => {
25846
+ if (deps2.context.provider?.id !== providerId) return;
25847
+ const cur = state.getConfig();
25848
+ const providerCfg = cur.providers?.[providerId] ?? { type: providerId };
25849
+ const routedCfg = routeProviderCfgThroughProxy(providerCfg, cur.baseUrl, providerId);
25850
+ const built = deps2.providerRegistry.has(providerId) ? deps2.providerRegistry.create({ ...routedCfg, type: providerId }) : makeProviderFromConfig4(providerId, routedCfg);
25851
+ const model = deps2.context.model ?? cur.model ?? "";
25852
+ const newProv = deps2.modelsRegistry ? await withCatalogCapabilities2(deps2.modelsRegistry, providerId, built, {
25853
+ ...routedCfg,
25854
+ type: providerId,
25855
+ model
25856
+ }) : built;
25857
+ deps2.context.provider = newProv;
25858
+ void updateAutoCompactionMaxContext(newProv, providerId).catch(() => void 0);
25859
+ });
25860
+ },
25861
+ logger: deps2.logger
25862
+ });
25863
+ return () => instantApply.dispose();
25864
+ }
25865
+
25784
25866
  // src/server/start-webui-remediation.ts
25785
25867
  import { randomUUID as randomUUID4 } from "node:crypto";
25786
25868
  import { toLanguagePackageInput } from "@wrongstack/techstack";
@@ -25870,6 +25952,7 @@ function setupWebuiShutdown(options) {
25870
25952
  await options.todosCheckpoint.detach();
25871
25953
  await options.stopHeapWatchdog();
25872
25954
  options.getCredentialWatcherClose()?.();
25955
+ options.getProxyInstantApplyDispose()();
25873
25956
  options.disposeRealtimeHandlers();
25874
25957
  const governanceCleanup = await options.governanceHandle?.close();
25875
25958
  if (governanceCleanup && !governanceCleanup.ok) {
@@ -26416,6 +26499,11 @@ async function startWebUI(opts = {}) {
26416
26499
  clients,
26417
26500
  updateAutoCompactionMaxContext
26418
26501
  });
26502
+ const proxyInstantApplyDispose = setupWebuiProxyInstantApply({
26503
+ state,
26504
+ deps: deps2,
26505
+ updateAutoCompactionMaxContext
26506
+ });
26419
26507
  const stopHeapWatchdog = startSharedHeapWatchdog({
26420
26508
  collectStats: () => ({
26421
26509
  surface: opts.surface ?? "webui",
@@ -26523,6 +26611,7 @@ projectRoot: ${ev.projectRoot ?? "?"}`,
26523
26611
  todosCheckpoint,
26524
26612
  stopHeapWatchdog,
26525
26613
  getCredentialWatcherClose: () => credentialWatcherClose,
26614
+ getProxyInstantApplyDispose: () => proxyInstantApplyDispose,
26526
26615
  disposeRealtimeHandlers,
26527
26616
  governanceHandle,
26528
26617
  logger,
@@ -0,0 +1,38 @@
1
+ /**
2
+ * WrongProxy instant-apply for the standalone WebUI server.
3
+ *
4
+ * Mirrors the CLI-side wiring in `setupProviderRuntime` (packages/cli/src/
5
+ * wiring/provider-runtime-setup.ts): subscribe to material proxy-config
6
+ * changes via `createProxyInstantApply` and rebuild the LIVE provider when
7
+ * the routing verdict for the active provider flips, so a Settings toggle
8
+ * or probe deactivation takes effect immediately instead of on the next
9
+ * incidental provider build.
10
+ *
11
+ * The rebuild sequence mirrors `applyModelSwitchCore` (routes.ts) — route
12
+ * the cfg through `routeProviderCfgThroughProxy`, build via registry or
13
+ * `makeProviderFromConfig`, overlay the live model's catalog capabilities
14
+ * — minus the parts that don't apply when provider+model are unchanged
15
+ * (no config persist, no session.start spam). The swap itself runs inside
16
+ * `runModelTransition` with a superseded-check so a queued rebuild can
17
+ * never overwrite a newer /model switch.
18
+ *
19
+ * In the CLI-hosted path this server module is NOT wired (the CLI's own
20
+ * `setupProviderRuntime` instant-apply covers the shared agent context),
21
+ * so there is exactly one rebuilder per process.
22
+ */
23
+ import type { Provider, ProviderConfig } from '@wrongstack/core/types';
24
+ import type { WebuiDeps, WebuiMutableState } from './routes.js';
25
+ export interface WebuiProxyApplyOptions {
26
+ state: WebuiMutableState;
27
+ deps: WebuiDeps;
28
+ /** Mirrors `cb.updateAutoCompactionMaxContext` in start-webui.ts. */
29
+ updateAutoCompactionMaxContext: (provider: Provider, providerId?: string, providerCfg?: ProviderConfig | undefined) => Promise<void>;
30
+ }
31
+ /**
32
+ * Wire the standalone server's WrongProxy instant-apply. Returns the
33
+ * dispose function for shutdown wiring. The helper itself lives in
34
+ * `@wrongstack/core` so both hosts share the identical change-detection
35
+ * semantics (effective-URL comparison, serialized rebuilds).
36
+ */
37
+ export declare function setupWebuiProxyInstantApply(options: WebuiProxyApplyOptions): () => void;
38
+ //# sourceMappingURL=start-webui-proxy-apply.d.ts.map
@@ -18,6 +18,7 @@ export declare function setupWebuiShutdown(options: {
18
18
  };
19
19
  stopHeapWatchdog: () => Promise<void>;
20
20
  getCredentialWatcherClose: () => (() => void) | undefined;
21
+ getProxyInstantApplyDispose: () => () => void;
21
22
  disposeRealtimeHandlers: () => void;
22
23
  governanceHandle?: {
23
24
  close: () => Promise<{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/webui-server",
3
- "version": "0.310.1",
3
+ "version": "0.313.1",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack WebUI HTTP/WebSocket server module — extracted from @wrongstack/webui in PR #243/244 to remove the CLI -> @wrongstack/webui/server cross-package edge (audit §3.1.1). Pure backend: HTTP routes, WebSocket handlers, MCP tool wrappers, HTML serving. The web frontend lives in @wrongstack/webui; this package is the standalone server it can run on.",
6
6
  "keywords": [
@@ -36,18 +36,19 @@
36
36
  ],
37
37
  "dependencies": {
38
38
  "ws": "^8.21.3",
39
- "@wrongstack/core": "0.310.1",
40
- "@wrongstack/kanban": "0.310.1",
41
- "@wrongstack/mcp": "0.310.1",
42
- "@wrongstack/sage": "0.310.1",
43
- "@wrongstack/runtime": "0.310.1",
44
- "@wrongstack/providers": "0.310.1",
45
- "@wrongstack/sdd": "0.310.1",
46
- "@wrongstack/tools": "0.310.1",
47
- "@wrongstack/requirement-intake": "0.310.1",
48
- "@wrongstack/vector-memory": "0.310.1",
49
- "@wrongstack/techstack": "0.310.1",
50
- "@wrongstack/webui-protocol": "0.310.1"
39
+ "@wrongstack/core": "0.313.1",
40
+ "@wrongstack/providers": "0.313.1",
41
+ "@wrongstack/runtime": "0.313.1",
42
+ "@wrongstack/kanban": "0.313.1",
43
+ "@wrongstack/sage": "0.313.1",
44
+ "@wrongstack/sdd": "0.313.1",
45
+ "@wrongstack/vector-memory": "0.313.1",
46
+ "@wrongstack/mcp": "0.313.1",
47
+ "@wrongstack/techstack": "0.313.1",
48
+ "@wrongstack/requirement-intake": "0.313.1",
49
+ "@wrongstack/tools": "0.313.1",
50
+ "@wrongstack/webui-protocol": "0.313.1",
51
+ "@wrongstack/wrongtrace": "0.313.1"
51
52
  },
52
53
  "devDependencies": {
53
54
  "@types/node": "^26.2.0",