@wrongstack/webui-server 0.291.0 → 0.291.2

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.
@@ -1813,15 +1813,15 @@ async function handleGitChanges(ws, projectRoot) {
1813
1813
  if (!m) continue;
1814
1814
  const added = m[1] === "-" ? 0 : Number(m[1]);
1815
1815
  const deleted = m[2] === "-" ? 0 : Number(m[2]);
1816
- let path23 = m[3] ?? "";
1817
- if (path23 === "") {
1816
+ let path24 = m[3] ?? "";
1817
+ if (path24 === "") {
1818
1818
  i += 1;
1819
- path23 = parts[i + 1] ?? parts[i] ?? "";
1819
+ path24 = parts[i + 1] ?? parts[i] ?? "";
1820
1820
  i += 1;
1821
1821
  }
1822
- if (!path23) continue;
1823
- const prev = counts.get(path23) ?? { added: 0, deleted: 0 };
1824
- counts.set(path23, { added: prev.added + added, deleted: prev.deleted + deleted });
1822
+ if (!path24) continue;
1823
+ const prev = counts.get(path24) ?? { added: 0, deleted: 0 };
1824
+ counts.set(path24, { added: prev.added + added, deleted: prev.deleted + deleted });
1825
1825
  }
1826
1826
  };
1827
1827
  parseNumstat(unstagedNumstat);
@@ -1833,7 +1833,7 @@ async function handleGitChanges(ws, projectRoot) {
1833
1833
  if (!rec || rec.length < 3) continue;
1834
1834
  const x = rec[0] ?? " ";
1835
1835
  const y = rec[1] ?? " ";
1836
- const path23 = rec.slice(3);
1836
+ const path24 = rec.slice(3);
1837
1837
  const isRename = x === "R" || x === "C" || y === "R" || y === "C";
1838
1838
  if (isRename) i += 1;
1839
1839
  let status;
@@ -1845,13 +1845,13 @@ async function handleGitChanges(ws, projectRoot) {
1845
1845
  else if (x === "D" || y === "D") status = "D";
1846
1846
  else status = "M";
1847
1847
  const staged = x !== " " && x !== "?";
1848
- let added = counts.get(path23)?.added ?? 0;
1849
- let deleted = counts.get(path23)?.deleted ?? 0;
1848
+ let added = counts.get(path24)?.added ?? 0;
1849
+ let deleted = counts.get(path24)?.deleted ?? 0;
1850
1850
  if (status === "?") {
1851
1851
  added = 0;
1852
1852
  deleted = 0;
1853
1853
  }
1854
- files.push({ path: path23, status, added, deleted, staged });
1854
+ files.push({ path: path24, status, added, deleted, staged });
1855
1855
  }
1856
1856
  send(ws, { type: "git.changes", payload: { files } });
1857
1857
  } catch (err) {
@@ -1862,10 +1862,10 @@ async function handleGitChanges(ws, projectRoot) {
1862
1862
  }
1863
1863
  }
1864
1864
  var MAX_DIFF_BYTES = 2 * 1024 * 1024;
1865
- async function handleGitDiff(ws, projectRoot, path23) {
1865
+ async function handleGitDiff(ws, projectRoot, path24) {
1866
1866
  const cwd = projectRoot || void 0;
1867
- const reply = (extra) => send(ws, { type: "git.diff", payload: { path: path23, ...extra } });
1868
- if (!path23 || path23.includes("\0") || path23.includes("..") || nodePath.isAbsolute(path23)) {
1867
+ const reply = (extra) => send(ws, { type: "git.diff", payload: { path: path24, ...extra } });
1868
+ if (!path24 || path24.includes("\0") || path24.includes("..") || nodePath.isAbsolute(path24)) {
1869
1869
  reply({ oldText: "", newText: "", error: "invalid path" });
1870
1870
  return;
1871
1871
  }
@@ -1873,10 +1873,10 @@ async function handleGitDiff(ws, projectRoot, path23) {
1873
1873
  const git = makeGit(cwd);
1874
1874
  const { readFile: readFile10 } = await import("node:fs/promises");
1875
1875
  const { join: join14 } = await import("node:path");
1876
- const oldText = await git(["show", `HEAD:${path23}`]);
1876
+ const oldText = await git(["show", `HEAD:${path24}`]);
1877
1877
  let newText = "";
1878
1878
  try {
1879
- const abs = cwd ? join14(cwd, path23) : path23;
1879
+ const abs = cwd ? join14(cwd, path24) : path24;
1880
1880
  const buf = await readFile10(abs);
1881
1881
  if (buf.includes(0)) {
1882
1882
  reply({ oldText: "", newText: "", binary: true });
@@ -3750,6 +3750,44 @@ async function handleSuperMemoryList(ws, memoryStore) {
3750
3750
  send(ws, { type: "memory.super.list", payload: { error: errMessage(err) } });
3751
3751
  }
3752
3752
  }
3753
+ async function handleSuperMemoryListPage(ws, msg, memoryStore) {
3754
+ if (!isSuperMemoryStore(memoryStore)) {
3755
+ send(ws, { type: "memory.super.listPage", payload: { error: requiresSuperMemory("memory.super.listPage") } });
3756
+ return;
3757
+ }
3758
+ try {
3759
+ const payload = msg.payload ?? {};
3760
+ const options = {
3761
+ statuses: Array.isArray(payload["statuses"]) ? payload["statuses"].filter((s) => typeof s === "string") : void 0,
3762
+ kind: typeof payload["kind"] === "string" ? payload["kind"] : void 0,
3763
+ query: typeof payload["query"] === "string" ? payload["query"] : void 0,
3764
+ limit: typeof payload["limit"] === "number" ? payload["limit"] : void 0,
3765
+ cursor: typeof payload["cursor"] === "string" ? payload["cursor"] : void 0
3766
+ };
3767
+ if (typeof memoryStore.listSuperPage === "function") {
3768
+ const page = await memoryStore.listSuperPage(options);
3769
+ send(ws, { type: "memory.super.listPage", payload: page });
3770
+ return;
3771
+ }
3772
+ const allowed = options.statuses && options.statuses.length > 0 ? new Set(options.statuses) : void 0;
3773
+ const everything = await memoryStore.listSuper();
3774
+ const statusCounts = {};
3775
+ for (const m of everything) statusCounts[m.status] = (statusCounts[m.status] ?? 0) + 1;
3776
+ const kind = options.kind && options.kind !== "all" ? options.kind : void 0;
3777
+ const q = options.query?.trim().toLowerCase();
3778
+ const filtered = everything.filter((m) => {
3779
+ if (allowed) return allowed.has(m.status);
3780
+ return m.status !== "deleted";
3781
+ }).filter((m) => !kind || m.kind === kind).filter((m) => !q || m.text.toLowerCase().includes(q));
3782
+ const limit = Math.max(1, Math.min(500, Math.floor(options.limit ?? 50)));
3783
+ send(ws, {
3784
+ type: "memory.super.listPage",
3785
+ payload: { memories: filtered.slice(0, limit), nextCursor: null, total: filtered.length, statusCounts }
3786
+ });
3787
+ } catch (err) {
3788
+ send(ws, { type: "memory.super.listPage", payload: { error: errMessage(err) } });
3789
+ }
3790
+ }
3753
3791
  async function handleSuperMemoryGet(ws, msg, memoryStore) {
3754
3792
  if (!isSuperMemoryStore(memoryStore)) {
3755
3793
  send(ws, { type: "memory.super.get", payload: { error: requiresSuperMemory("memory.super.get") } });
@@ -4299,7 +4337,7 @@ async function loadSavedProviders(configPath, vault) {
4299
4337
  if (!parsed.providers) return {};
4300
4338
  return decryptConfigSecrets(parsed.providers, vault);
4301
4339
  }
4302
- async function saveProviders(configPath, vault, providers) {
4340
+ async function saveProviders(configPath, vault, providers, profileConfigPath) {
4303
4341
  let raw;
4304
4342
  let fileExists = true;
4305
4343
  try {
@@ -4333,6 +4371,23 @@ async function saveProviders(configPath, vault, providers) {
4333
4371
  parsed.providers = providers;
4334
4372
  const encrypted = encryptConfigSecrets(parsed, vault);
4335
4373
  await atomicWrite4(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
4374
+ if (profileConfigPath && profileConfigPath !== configPath) {
4375
+ let profileRaw;
4376
+ try {
4377
+ profileRaw = await fs8.readFile(profileConfigPath, "utf8");
4378
+ } catch {
4379
+ profileRaw = "{}";
4380
+ }
4381
+ let profileParsed;
4382
+ try {
4383
+ profileParsed = JSON.parse(profileRaw);
4384
+ } catch {
4385
+ return;
4386
+ }
4387
+ profileParsed.providers = providers;
4388
+ const profileEncrypted = encryptConfigSecrets(profileParsed, vault);
4389
+ await atomicWrite4(profileConfigPath, JSON.stringify(profileEncrypted, null, 2), { mode: 384 });
4390
+ }
4336
4391
  }
4337
4392
 
4338
4393
  // src/server/provider-keys.ts
@@ -5247,34 +5302,34 @@ var ENUM_PREF_KEYS = {
5247
5302
  chimeraAutoFix: /* @__PURE__ */ new Set(["off", "ask", "auto"]),
5248
5303
  autoReviewCascadeOn: /* @__PURE__ */ new Set(["off", "critical", "high"])
5249
5304
  };
5250
- function validateModelRuntimeValue(modelRuntime, path23) {
5305
+ function validateModelRuntimeValue(modelRuntime, path24) {
5251
5306
  const reasoning = modelRuntime["reasoning"];
5252
5307
  if (reasoning !== void 0) {
5253
- if (!isRecord(reasoning)) return `${path23}.reasoning must be an object when provided`;
5308
+ if (!isRecord(reasoning)) return `${path24}.reasoning must be an object when provided`;
5254
5309
  const mode = reasoning["mode"];
5255
5310
  const effort = reasoning["effort"];
5256
5311
  const preserve = reasoning["preserve"];
5257
5312
  if (mode !== void 0 && (typeof mode !== "string" || !REASONING_MODE_VALUES.has(mode))) {
5258
- return `${path23}.reasoning.mode must be one of: ${Array.from(REASONING_MODE_VALUES).join(", ")}`;
5313
+ return `${path24}.reasoning.mode must be one of: ${Array.from(REASONING_MODE_VALUES).join(", ")}`;
5259
5314
  }
5260
5315
  if (effort !== void 0 && (typeof effort !== "string" || !REASONING_EFFORT_VALUES.has(effort))) {
5261
- return `${path23}.reasoning.effort must be one of: ${Array.from(REASONING_EFFORT_VALUES).join(", ")}`;
5316
+ return `${path24}.reasoning.effort must be one of: ${Array.from(REASONING_EFFORT_VALUES).join(", ")}`;
5262
5317
  }
5263
5318
  if (preserve !== void 0 && typeof preserve !== "boolean") {
5264
- return `${path23}.reasoning.preserve must be a boolean when provided`;
5319
+ return `${path24}.reasoning.preserve must be a boolean when provided`;
5265
5320
  }
5266
5321
  }
5267
5322
  const cache = modelRuntime["cache"];
5268
5323
  if (cache !== void 0) {
5269
- if (!isRecord(cache)) return `${path23}.cache must be an object when provided`;
5324
+ if (!isRecord(cache)) return `${path24}.cache must be an object when provided`;
5270
5325
  const ttl = cache["ttl"];
5271
5326
  if (ttl !== void 0 && (typeof ttl !== "string" || !CACHE_TTL_VALUES.has(ttl) || ttl === "default")) {
5272
- return `${path23}.cache.ttl must be one of: 5m, 1h`;
5327
+ return `${path24}.cache.ttl must be one of: 5m, 1h`;
5273
5328
  }
5274
5329
  }
5275
5330
  const parameters = modelRuntime["parameters"];
5276
5331
  if (parameters !== void 0 && !isRecord(parameters)) {
5277
- return `${path23}.parameters must be an object when provided`;
5332
+ return `${path24}.parameters must be an object when provided`;
5278
5333
  }
5279
5334
  return null;
5280
5335
  }
@@ -5567,8 +5622,8 @@ function validateShellOpenPayload(payload) {
5567
5622
  if (!isRecord(payload)) {
5568
5623
  return { ok: false, message: "shell.open payload must be an object with string path" };
5569
5624
  }
5570
- const path23 = payload["path"];
5571
- if (typeof path23 !== "string" || path23.trim().length === 0) {
5625
+ const path24 = payload["path"];
5626
+ if (typeof path24 !== "string" || path24.trim().length === 0) {
5572
5627
  return { ok: false, message: "shell.open payload.path must be a non-empty string" };
5573
5628
  }
5574
5629
  const target = payload["target"];
@@ -5581,7 +5636,7 @@ function validateShellOpenPayload(payload) {
5581
5636
  return {
5582
5637
  ok: true,
5583
5638
  value: {
5584
- path: path23,
5639
+ path: path24,
5585
5640
  ...target !== void 0 ? { target } : {}
5586
5641
  }
5587
5642
  };
@@ -5590,14 +5645,14 @@ function validateGitDiffPayload(payload) {
5590
5645
  if (!isRecord(payload)) {
5591
5646
  return { ok: false, message: "git.diff payload must be an object" };
5592
5647
  }
5593
- const path23 = payload["path"];
5594
- if (path23 === void 0 || path23 === null) {
5648
+ const path24 = payload["path"];
5649
+ if (path24 === void 0 || path24 === null) {
5595
5650
  return { ok: true, value: { path: "" } };
5596
5651
  }
5597
- if (typeof path23 !== "string") {
5652
+ if (typeof path24 !== "string") {
5598
5653
  return { ok: false, message: "git.diff payload.path must be a string when provided" };
5599
5654
  }
5600
- return { ok: true, value: { path: path23 } };
5655
+ return { ok: true, value: { path: path24 } };
5601
5656
  }
5602
5657
 
5603
5658
  // src/server/zip.ts
@@ -8927,7 +8982,7 @@ function isSuperMemoryService(memoryStore) {
8927
8982
  }
8928
8983
 
8929
8984
  // src/server/start-webui.ts
8930
- import * as path22 from "node:path";
8985
+ import * as path23 from "node:path";
8931
8986
  import {
8932
8987
  createDefaultPipelines,
8933
8988
  createSessionEventBridge,
@@ -12695,6 +12750,8 @@ function createMessageDispatcher(opts) {
12695
12750
  // ── SuperMemory operations ──
12696
12751
  case "memory.super.list":
12697
12752
  return handleSuperMemoryList(ws, deps2.memoryStore);
12753
+ case "memory.super.listPage":
12754
+ return handleSuperMemoryListPage(ws, msg, deps2.memoryStore);
12698
12755
  case "memory.super.get":
12699
12756
  return handleSuperMemoryGet(ws, msg, deps2.memoryStore);
12700
12757
  case "memory.super.update":
@@ -13046,8 +13103,9 @@ function createMessageDispatcher(opts) {
13046
13103
 
13047
13104
  // src/server/pref-helpers.ts
13048
13105
  import * as fs14 from "node:fs/promises";
13106
+ import * as path20 from "node:path";
13049
13107
  import { decryptConfigSecrets as decryptConfigSecrets2, encryptConfigSecrets as encryptConfigSecrets2 } from "@wrongstack/core/security";
13050
- import { atomicWrite as atomicWrite6, FORBIDDEN_PROTO_KEYS as FORBIDDEN_PROTO_KEYS2 } from "@wrongstack/core/utils";
13108
+ import { atomicWrite as atomicWrite6, backupConfigFile, FORBIDDEN_PROTO_KEYS as FORBIDDEN_PROTO_KEYS2 } from "@wrongstack/core/utils";
13051
13109
  var PREF_KEYS = [
13052
13110
  "autonomy",
13053
13111
  "autonomyDelayMs",
@@ -13136,26 +13194,34 @@ function prefSnapshot(contextMeta) {
13136
13194
  }
13137
13195
  return snapshot;
13138
13196
  }
13197
+ async function writeGlobalConfigFile(filePath, vault, mutate, logger, errorLabel) {
13198
+ const globalRoot = path20.dirname(filePath);
13199
+ await backupConfigFile(filePath, { globalRoot });
13200
+ let raw;
13201
+ try {
13202
+ raw = await fs14.readFile(filePath, "utf8");
13203
+ } catch {
13204
+ raw = "{}";
13205
+ }
13206
+ let parsed;
13207
+ try {
13208
+ parsed = JSON.parse(raw);
13209
+ } catch {
13210
+ logger.warn(`${errorLabel}: refusing to overwrite corrupt config at ${filePath}`);
13211
+ return;
13212
+ }
13213
+ const decrypted = decryptConfigSecrets2(parsed, vault);
13214
+ mutate(decrypted);
13215
+ const encrypted = encryptConfigSecrets2(decrypted, vault);
13216
+ await atomicWrite6(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
13217
+ }
13139
13218
  async function updateGlobalConfig(deps2, holder, mutate, errorLabel) {
13140
- const { globalConfigPath, vault, logger } = deps2;
13219
+ const { globalConfigPath, profileConfigPath, vault, logger } = deps2;
13141
13220
  const write = async () => {
13142
- let raw;
13143
- try {
13144
- raw = await fs14.readFile(globalConfigPath, "utf8");
13145
- } catch {
13146
- raw = "{}";
13221
+ await writeGlobalConfigFile(globalConfigPath, vault, mutate, logger, errorLabel);
13222
+ if (profileConfigPath && profileConfigPath !== globalConfigPath) {
13223
+ await writeGlobalConfigFile(profileConfigPath, vault, mutate, logger, errorLabel);
13147
13224
  }
13148
- let parsed;
13149
- try {
13150
- parsed = JSON.parse(raw);
13151
- } catch {
13152
- logger.warn(`${errorLabel}: refusing to overwrite corrupt config at ${globalConfigPath}`);
13153
- return;
13154
- }
13155
- const decrypted = decryptConfigSecrets2(parsed, vault);
13156
- mutate(decrypted);
13157
- const encrypted = encryptConfigSecrets2(decrypted, vault);
13158
- await atomicWrite6(globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
13159
13225
  };
13160
13226
  const next = holder.lock.then(write);
13161
13227
  holder.lock = next.then(
@@ -13472,13 +13538,13 @@ async function probeModelDescriptors(cfg) {
13472
13538
  }
13473
13539
  }
13474
13540
  function createProviderHandlers(deps2) {
13475
- const { globalConfigPath, vault, broadcast: broadcast2, clients } = deps2;
13541
+ const { globalConfigPath, profileConfigPath, vault, broadcast: broadcast2, clients } = deps2;
13476
13542
  let configWriteLock = deps2.getConfigWriteLock();
13477
13543
  async function loadConfigProviders() {
13478
13544
  return loadSavedProviders(globalConfigPath, vault);
13479
13545
  }
13480
13546
  async function saveConfigProviders(providers) {
13481
- const next = configWriteLock.then(() => saveProviders(globalConfigPath, vault, providers)).catch((err) => {
13547
+ const next = configWriteLock.then(() => saveProviders(globalConfigPath, vault, providers, profileConfigPath)).catch((err) => {
13482
13548
  const msg = toErrorMessage9(err);
13483
13549
  console.error(JSON.stringify({
13484
13550
  level: "error",
@@ -13753,7 +13819,7 @@ function createProviderHandlers(deps2) {
13753
13819
  }
13754
13820
 
13755
13821
  // src/server/routes.ts
13756
- import path21 from "node:path";
13822
+ import path22 from "node:path";
13757
13823
  import {
13758
13824
  buildRefinerContextSections,
13759
13825
  enhanceUserPrompt,
@@ -13964,7 +14030,7 @@ function createModeHandlers(ctx) {
13964
14030
  }
13965
14031
 
13966
14032
  // src/server/project-handlers.ts
13967
- import * as path20 from "node:path";
14033
+ import * as path21 from "node:path";
13968
14034
  function createProjectHandlers(ctx) {
13969
14035
  return {
13970
14036
  listProjects: async (ws) => {
@@ -13990,7 +14056,7 @@ function createProjectHandlers(ctx) {
13990
14056
  selectProject: async (ws, msg) => {
13991
14057
  const payload = msg.payload;
13992
14058
  const root = typeof payload?.root === "string" ? payload.root : "";
13993
- const name2 = typeof payload?.name === "string" ? payload.name : root ? path20.basename(root) : "";
14059
+ const name2 = typeof payload?.name === "string" ? payload.name : root ? path21.basename(root) : "";
13994
14060
  send(ws, {
13995
14061
  type: "projects.selected",
13996
14062
  payload: {
@@ -14444,7 +14510,9 @@ async function enrichProviderModelDescriptors(modelsRegistry, providerId, cfg, m
14444
14510
  if (resolved.capabilities.vision) capabilities.add("vision");
14445
14511
  return {
14446
14512
  ...model,
14447
- contextWindow: model.contextWindow || resolved.capabilities.maxContext || void 0,
14513
+ contextWindow: model.contextWindow ?? resolved.capabilities.maxContext ?? void 0,
14514
+ inputCost: model.inputCost ?? resolved.cost?.input,
14515
+ outputCost: model.outputCost ?? resolved.cost?.output,
14448
14516
  capabilities: [...capabilities]
14449
14517
  };
14450
14518
  })
@@ -14453,6 +14521,7 @@ async function enrichProviderModelDescriptors(modelsRegistry, providerId, cfg, m
14453
14521
  function buildRoutes(state, deps2, cb) {
14454
14522
  const providerHandlers = createProviderHandlers({
14455
14523
  globalConfigPath: deps2.globalConfigPath,
14524
+ profileConfigPath: deps2.profileConfigPath,
14456
14525
  vault: deps2.vault,
14457
14526
  getConfigWriteLock: state.getConfigWriteLock,
14458
14527
  setConfigWriteLock: state.setConfigWriteLock,
@@ -14920,7 +14989,7 @@ function buildRoutes(state, deps2, cb) {
14920
14989
  }
14921
14990
  return handleMailboxMessages(
14922
14991
  ws,
14923
- { projectRoot: state.getProjectRoot(), globalRoot: path21.dirname(deps2.globalConfigPath) },
14992
+ { projectRoot: state.getProjectRoot(), globalRoot: path22.dirname(deps2.globalConfigPath) },
14924
14993
  parsed.value
14925
14994
  );
14926
14995
  },
@@ -14932,13 +15001,13 @@ function buildRoutes(state, deps2, cb) {
14932
15001
  }
14933
15002
  return handleMailboxAgents(
14934
15003
  ws,
14935
- { projectRoot: state.getProjectRoot(), globalRoot: path21.dirname(deps2.globalConfigPath) },
15004
+ { projectRoot: state.getProjectRoot(), globalRoot: path22.dirname(deps2.globalConfigPath) },
14936
15005
  parsed.value
14937
15006
  );
14938
15007
  },
14939
15008
  clear: (ws) => handleMailboxClear(ws, {
14940
15009
  projectRoot: state.getProjectRoot(),
14941
- globalRoot: path21.dirname(deps2.globalConfigPath)
15010
+ globalRoot: path22.dirname(deps2.globalConfigPath)
14942
15011
  }),
14943
15012
  purge: (ws, msg) => {
14944
15013
  const parsed = validateMailboxPurgePayload(msg.payload);
@@ -14948,14 +15017,14 @@ function buildRoutes(state, deps2, cb) {
14948
15017
  }
14949
15018
  return handleMailboxPurge(
14950
15019
  ws,
14951
- { projectRoot: state.getProjectRoot(), globalRoot: path21.dirname(deps2.globalConfigPath) },
15020
+ { projectRoot: state.getProjectRoot(), globalRoot: path22.dirname(deps2.globalConfigPath) },
14952
15021
  parsed.value
14953
15022
  );
14954
15023
  },
14955
15024
  compact: (ws, msg) => {
14956
15025
  return handleMailboxCompact(
14957
15026
  ws,
14958
- { projectRoot: state.getProjectRoot(), globalRoot: path21.dirname(deps2.globalConfigPath) },
15027
+ { projectRoot: state.getProjectRoot(), globalRoot: path22.dirname(deps2.globalConfigPath) },
14959
15028
  msg.payload ?? {}
14960
15029
  );
14961
15030
  }
@@ -15106,7 +15175,9 @@ async function startWebUI(opts = {}) {
15106
15175
  let projectRoot = boot.projectRoot;
15107
15176
  let workingDir = projectRoot;
15108
15177
  const configWriteLock = { lock: Promise.resolve() };
15109
- const prefHelperDeps = { globalConfigPath, vault, logger };
15178
+ const activeProfile = config.activeProfile ?? "default";
15179
+ const profileConfigPath = wpaths.profileConfig(activeProfile);
15180
+ const prefHelperDeps = { globalConfigPath, profileConfigPath, vault, logger };
15110
15181
  const updateGlobalConfig2 = async (mutate, errorLabel) => updateGlobalConfig(prefHelperDeps, configWriteLock, mutate, errorLabel);
15111
15182
  console.log("[WebUI] Config loaded:", config.provider ?? "(none)", "/", config.model ?? "(none)");
15112
15183
  if (!config.provider && config.providers && typeof config.providers === "object" && config.providers !== null && !Array.isArray(config.providers) && Object.keys(config.providers).length > 0) {
@@ -15268,21 +15339,21 @@ async function startWebUI(opts = {}) {
15268
15339
  wpaths
15269
15340
  }, watcherMetricsRef);
15270
15341
  async function touchProjectEntry(root, workDir) {
15271
- const resolved = path22.resolve(root);
15342
+ const resolved = path23.resolve(root);
15272
15343
  const manifest = await loadManifest(globalConfigPath);
15273
15344
  const now = (/* @__PURE__ */ new Date()).toISOString();
15274
- const existing = manifest.projects.find((p) => path22.resolve(p.root) === resolved);
15345
+ const existing = manifest.projects.find((p) => path23.resolve(p.root) === resolved);
15275
15346
  if (existing) {
15276
15347
  existing.lastSeen = now;
15277
- if (workDir) existing.lastWorkingDir = path22.resolve(workDir);
15348
+ if (workDir) existing.lastWorkingDir = path23.resolve(workDir);
15278
15349
  } else {
15279
15350
  manifest.projects.push({
15280
- name: path22.basename(resolved),
15351
+ name: path23.basename(resolved),
15281
15352
  root: resolved,
15282
15353
  slug: generateProjectSlug(resolved),
15283
15354
  createdAt: now,
15284
15355
  lastSeen: now,
15285
- lastWorkingDir: workDir ? path22.resolve(workDir) : void 0
15356
+ lastWorkingDir: workDir ? path23.resolve(workDir) : void 0
15286
15357
  });
15287
15358
  }
15288
15359
  await saveManifest(manifest, globalConfigPath);
@@ -15389,6 +15460,7 @@ async function startWebUI(opts = {}) {
15389
15460
  persistPrefsToConfig: persistPrefsToConfig2,
15390
15461
  prefSnapshot: prefSnapshot2
15391
15462
  };
15463
+ const watchConfigPath = profileConfigPath ?? globalConfigPath;
15392
15464
  let credentialWatcherClose;
15393
15465
  if (process.env["WRONGSTACK_DISABLE_CONFIG_WATCH"] !== "1") {
15394
15466
  let lastActiveCfg = JSON.stringify(
@@ -15396,7 +15468,7 @@ async function startWebUI(opts = {}) {
15396
15468
  );
15397
15469
  let lastUiLocale = state.getConfig().uiLocale;
15398
15470
  const credentialWatcher = watchProviderConfig(
15399
- globalConfigPath,
15471
+ watchConfigPath,
15400
15472
  vault,
15401
15473
  (snapshot) => {
15402
15474
  state.setConfig(
@@ -15537,7 +15609,7 @@ async function startWebUI(opts = {}) {
15537
15609
  archiveLowConfidenceAfterDays: config.superMemory?.hygiene?.archiveLowConfidenceAfterDays
15538
15610
  }).catch((err) => logger.warn(`super-memory session hygiene failed: ${toErrorMessage10(err)}`));
15539
15611
  }
15540
- await unregisterInstance(process.pid, path22.dirname(globalConfigPath));
15612
+ await unregisterInstance(process.pid, path23.dirname(globalConfigPath));
15541
15613
  }
15542
15614
  });
15543
15615
  }