@wrongstack/webui-server 0.289.0 → 0.291.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1904,6 +1904,7 @@ async function handleGitDiff(ws, projectRoot, path24) {
1904
1904
  import * as fs6 from "node:fs/promises";
1905
1905
  import * as http from "node:http";
1906
1906
  import * as path7 from "node:path";
1907
+ import * as v8 from "node:v8";
1907
1908
 
1908
1909
  // src/server/http-server/api-handlers.ts
1909
1910
  async function handleApiSessions(res, globalRoot) {
@@ -3210,6 +3211,23 @@ function createHttpServer(opts) {
3210
3211
  }
3211
3212
  return;
3212
3213
  }
3214
+ if (url.pathname === "/debug/system" && req.method === "GET") {
3215
+ res.writeHead(200, {
3216
+ "Content-Type": "application/json",
3217
+ "Cache-Control": "no-store"
3218
+ });
3219
+ res.end(
3220
+ JSON.stringify({
3221
+ pid: process.pid,
3222
+ memoryUsage: process.memoryUsage(),
3223
+ heapLimit: v8.getHeapStatistics().heap_size_limit,
3224
+ uptime: process.uptime(),
3225
+ cpuUsage: process.cpuUsage(),
3226
+ timestamp: Date.now()
3227
+ })
3228
+ );
3229
+ return;
3230
+ }
3213
3231
  let filePath;
3214
3232
  if (url.pathname === "/" || url.pathname === "") {
3215
3233
  filePath = path7.join(distDir, "index.html");
@@ -5192,6 +5210,7 @@ var BOOLEAN_PREF_KEYS = /* @__PURE__ */ new Set([
5192
5210
  "hqRawContent",
5193
5211
  "fallbackAuto",
5194
5212
  "favoriteModelsOnly",
5213
+ "modelAvailabilitySchedule",
5195
5214
  "breakerEnabled",
5196
5215
  "debugStream",
5197
5216
  // Chimera + auto-review master toggles
@@ -5336,7 +5355,10 @@ function validatePreferenceValue(key, value) {
5336
5355
  return `prefs.update payload.${key}.modelRuntime must be an object when provided`;
5337
5356
  }
5338
5357
  if (isRecord(modelRuntime)) {
5339
- const runtimeError = validateModelRuntimeValue(modelRuntime, `prefs.update payload.${key}.modelRuntime`);
5358
+ const runtimeError = validateModelRuntimeValue(
5359
+ modelRuntime,
5360
+ `prefs.update payload.${key}.modelRuntime`
5361
+ );
5340
5362
  if (runtimeError) return runtimeError;
5341
5363
  }
5342
5364
  if (model === void 0 && fallbackProfile === void 0 && modelRuntime === void 0) {
@@ -6648,7 +6670,7 @@ function registerShutdownHandlers(res) {
6648
6670
  import { watch as fsWatch } from "node:fs";
6649
6671
  import * as fs11 from "node:fs/promises";
6650
6672
  import * as path14 from "node:path";
6651
- import { getBoard, getKanbanDir } from "@wrongstack/kanban";
6673
+ import { getBoard, getKanbanDir, recordTaskFileActivity } from "@wrongstack/kanban";
6652
6674
 
6653
6675
  // src/server/codemap-telemetry.ts
6654
6676
  import * as path13 from "node:path";
@@ -7044,6 +7066,18 @@ function setupEvents(deps2) {
7044
7066
  on("file.activity", (e) => {
7045
7067
  broadcast2(clients, { type: "codemap.file_event", payload: e });
7046
7068
  });
7069
+ on("file.event", (e) => {
7070
+ if (e.scope !== "task" || !e.boardId || !e.taskId) return;
7071
+ void recordTaskFileActivity(context.projectRoot, e.boardId, e.taskId, e).then((recorded) => {
7072
+ if (recorded) {
7073
+ broadcast2(clients, {
7074
+ type: "kanban.task.activity.changed",
7075
+ payload: { boardId: e.boardId, taskId: e.taskId }
7076
+ });
7077
+ }
7078
+ }).catch(() => {
7079
+ });
7080
+ });
7047
7081
  on("tool.loop_detected", (e) => {
7048
7082
  broadcast2(clients, {
7049
7083
  type: "tool.loop_detected",
@@ -7168,12 +7202,14 @@ function setupEvents(deps2) {
7168
7202
  input: e.input,
7169
7203
  suggestedPattern: e.suggestedPattern,
7170
7204
  decisionSource: e.decisionSource,
7171
- riskTier: e.riskTier
7205
+ riskTier: e.riskTier,
7206
+ boundaryReason: e.boundaryReason
7172
7207
  });
7173
7208
  pendingConfirms.set(id, {
7174
7209
  resolve: e.resolve,
7175
7210
  decisionSource: e.decisionSource,
7176
7211
  riskTier: e.riskTier,
7212
+ boundaryReason: e.boundaryReason,
7177
7213
  payload
7178
7214
  });
7179
7215
  broadcast2(clients, { type: "tool.confirm_needed", payload });
@@ -7266,7 +7302,8 @@ function setupEvents(deps2) {
7266
7302
  oldState: e.oldState,
7267
7303
  newState: e.newState,
7268
7304
  reason: e.reason,
7269
- timestamp: e.timestamp
7305
+ timestamp: e.timestamp,
7306
+ stateExpiresAt: e.stateExpiresAt
7270
7307
  })
7271
7308
  });
7272
7309
  });
@@ -8373,6 +8410,7 @@ function seedContextMeta(config, context) {
8373
8410
  meta["fallbackProfiles"] = config.fallbackProfiles ?? {};
8374
8411
  meta["favoriteModels"] = config.favoriteModels ?? [];
8375
8412
  meta["favoriteModelsOnly"] = config.favoriteModelsOnly === true;
8413
+ meta["modelAvailabilitySchedule"] = config.modelAvailabilitySchedule ?? [];
8376
8414
  meta["modelMatrix"] = config.modelMatrix ?? {};
8377
8415
  meta["fallbackAuto"] = config.fallbackAuto !== false;
8378
8416
  if (typeof config.uiLocale === "string" && config.uiLocale) meta["uiLocale"] = config.uiLocale;
@@ -8455,9 +8493,7 @@ function seedContextMeta(config, context) {
8455
8493
  } catch {
8456
8494
  resolvedChain = [];
8457
8495
  }
8458
- meta["autoReviewFallbackModels"] = resolvedChain.map(
8459
- (e) => `${e.providerId}/${e.model}`
8460
- );
8496
+ meta["autoReviewFallbackModels"] = resolvedChain.map((e) => `${e.providerId}/${e.model}`);
8461
8497
  }
8462
8498
  }
8463
8499
 
@@ -9914,7 +9950,7 @@ function setupWebUICodebaseIndexing(deps2) {
9914
9950
  }
9915
9951
  if (idx) {
9916
9952
  cancelPendingReindexes();
9917
- shutdownCodebaseIndexHost();
9953
+ void shutdownCodebaseIndexHost();
9918
9954
  }
9919
9955
  }
9920
9956
  };
@@ -10081,6 +10117,9 @@ var DEFAULT_COLS = 80;
10081
10117
  var DEFAULT_ROWS = 24;
10082
10118
  var requireFromHere = createRequire4(import.meta.url);
10083
10119
  var cachedNodePty;
10120
+ function resolveTerminalShell(platform = process.platform, env = process.env) {
10121
+ return platform === "win32" ? env.COMSPEC || "cmd.exe" : env.SHELL || "/bin/sh";
10122
+ }
10084
10123
  var TerminalWebSocketHandler = class {
10085
10124
  constructor(getCwd, logger, loadNodePty = defaultLoadNodePty, killProcessTree = defaultKillProcessTree) {
10086
10125
  this.getCwd = getCwd;
@@ -10136,7 +10175,7 @@ var TerminalWebSocketHandler = class {
10136
10175
  });
10137
10176
  return;
10138
10177
  }
10139
- const shell = process.platform === "win32" ? process.env.COMSPEC || "cmd.exe" : process.env.SHELL || "/bin/bash";
10178
+ const shell = resolveTerminalShell();
10140
10179
  const nodePty = this.loadNodePty();
10141
10180
  if (!nodePty) {
10142
10181
  const msg = "Integrated terminal unavailable: optional dependency node-pty is not installed. Install node-pty to enable WebUI terminal sessions.";
@@ -10456,7 +10495,11 @@ async function createAgentServices(input) {
10456
10495
  toolExecutor
10457
10496
  });
10458
10497
  if (config.features.memory && config.features.memoryConsolidation !== false) {
10459
- agent.extensions.register(new SessionMemoryConsolidator({ memoryStore }));
10498
+ const consSuperMemory = typeof memoryStore["rememberSuper"] === "function" ? memoryStore : void 0;
10499
+ agent.extensions.register(new SessionMemoryConsolidator({
10500
+ memoryStore,
10501
+ ...consSuperMemory ? { superMemory: consSuperMemory } : {}
10502
+ }));
10460
10503
  }
10461
10504
  console.log("[WebUI] Agent initialized");
10462
10505
  const brainCfg = resolveBrainConfigDefaults(config.brain, {
@@ -10662,6 +10705,7 @@ function isSuperMemoryRetriever(memoryStore) {
10662
10705
  // src/server/pending-confirms.ts
10663
10706
  function resolveYoloEligiblePendingConfirms(pendingConfirms) {
10664
10707
  for (const [id, confirm] of pendingConfirms) {
10708
+ if (confirm.boundaryReason) continue;
10665
10709
  pendingConfirms.delete(id);
10666
10710
  confirm.resolve("yes");
10667
10711
  }
@@ -11141,7 +11185,7 @@ import {
11141
11185
  createBoard,
11142
11186
  duplicateBoard,
11143
11187
  exportBoardToTaskGraph,
11144
- generateBoardFromDescription,
11188
+ createBoardFromText,
11145
11189
  getBoard as getBoard2,
11146
11190
  getKanbanOrchestrationSnapshot,
11147
11191
  getKanbanQueueHealth,
@@ -11172,6 +11216,32 @@ import {
11172
11216
  updateTask
11173
11217
  } from "@wrongstack/kanban";
11174
11218
  import { applySessionKanbanTaskToSource } from "@wrongstack/tools/session-kanban";
11219
+ function paginateKanbanBoards(boards, input) {
11220
+ const pageSize = Math.min(100, Math.max(1, Math.floor(input.pageSize)));
11221
+ const activeSessionIds = new Set(input.activeSessionIds ?? []);
11222
+ const isActive = (board) => board.presence?.some((entry) => entry.active) === true || board.tags?.some(
11223
+ (tag) => tag.startsWith("session:") && activeSessionIds.has(tag.slice(8))
11224
+ ) === true;
11225
+ const sorted = [...boards].sort((left, right) => {
11226
+ const activityOrder = Number(isActive(right)) - Number(isActive(left));
11227
+ return activityOrder || right.updatedAt.localeCompare(left.updatedAt);
11228
+ });
11229
+ const activeTotal = sorted.filter(isActive).length;
11230
+ const total = sorted.length;
11231
+ const totalPages = Math.max(1, Math.ceil(total / pageSize));
11232
+ const requestedPage = Number.isFinite(input.page) ? Math.floor(input.page) : 1;
11233
+ const page = Math.min(totalPages, Math.max(1, requestedPage));
11234
+ const start = (page - 1) * pageSize;
11235
+ return {
11236
+ items: sorted.slice(start, start + pageSize),
11237
+ total,
11238
+ page,
11239
+ pageSize,
11240
+ totalPages,
11241
+ activeTotal,
11242
+ orphanedTotal: total - activeTotal
11243
+ };
11244
+ }
11175
11245
  async function syncSessionSource(ctx, task, remove = false) {
11176
11246
  if (!ctx.context) return;
11177
11247
  const update = await applySessionKanbanTaskToSource(ctx.context, task, { remove });
@@ -11221,9 +11291,26 @@ async function handleKanbanRoute(ws, msg, ctx) {
11221
11291
  const type = msg.type;
11222
11292
  try {
11223
11293
  switch (type) {
11224
- case "kanban.list":
11225
- ok(ws, type, await listBoards(ctx.projectRoot));
11294
+ case "kanban.list": {
11295
+ const boards = await listBoards(ctx.projectRoot);
11296
+ const requestedPage = Number(payload?.page);
11297
+ const requestedPageSize = Number(payload?.pageSize);
11298
+ if (!Number.isFinite(requestedPage) || !Number.isFinite(requestedPageSize)) {
11299
+ ok(ws, type, boards);
11300
+ return true;
11301
+ }
11302
+ const activeSessionIds = Array.isArray(payload?.activeSessionIds) ? payload.activeSessionIds.filter((id) => typeof id === "string") : [];
11303
+ ok(
11304
+ ws,
11305
+ type,
11306
+ paginateKanbanBoards(boards, {
11307
+ page: requestedPage,
11308
+ pageSize: requestedPageSize,
11309
+ activeSessionIds
11310
+ })
11311
+ );
11226
11312
  return true;
11313
+ }
11227
11314
  case "kanban.get": {
11228
11315
  const boardId = payload?.boardId;
11229
11316
  if (!boardId) {
@@ -11289,7 +11376,8 @@ async function handleKanbanRoute(ws, msg, ctx) {
11289
11376
  ...payload?.description ? { description: payload.description } : {},
11290
11377
  ...payload?.tags ? { tags: payload.tags } : {},
11291
11378
  ...payload?.columns ? { columns: payload.columns } : {},
11292
- ...has(payload, "lifecycle") ? { lifecycle: payload?.lifecycle } : {}
11379
+ ...has(payload, "lifecycle") ? { lifecycle: payload?.lifecycle } : {},
11380
+ ...has(payload, "boundary") ? { boundary: payload?.boundary } : {}
11293
11381
  })
11294
11382
  );
11295
11383
  return true;
@@ -11310,6 +11398,9 @@ async function handleKanbanRoute(ws, msg, ctx) {
11310
11398
  } : {},
11311
11399
  ...has(payload, "supervisor") ? {
11312
11400
  supervisor: payload?.supervisor ?? null
11401
+ } : {},
11402
+ ...has(payload, "boundary") ? {
11403
+ boundary: payload?.boundary ?? null
11313
11404
  } : {}
11314
11405
  });
11315
11406
  board ? ok(ws, type, board) : fail(ws, type, `Board not found: ${boardId}`);
@@ -11356,7 +11447,7 @@ async function handleKanbanRoute(ws, msg, ctx) {
11356
11447
  }
11357
11448
  const board = await createBoard(
11358
11449
  ctx.projectRoot,
11359
- generateBoardFromDescription({
11450
+ createBoardFromText({
11360
11451
  description,
11361
11452
  ...payload?.title ? { title: payload.title } : {},
11362
11453
  ...payload?.context ? { context: payload.context } : {}
@@ -11468,7 +11559,8 @@ async function handleKanbanRoute(ws, msg, ctx) {
11468
11559
  ...payload?.dueDate ? { dueDate: payload.dueDate } : {},
11469
11560
  ...payload?.priority ? { priority: payload.priority } : {},
11470
11561
  ...payload?.assignedAgent ? { assignedAgent: payload.assignedAgent } : {},
11471
- ...payload?.labels ? { labels: payload.labels } : {}
11562
+ ...payload?.labels ? { labels: payload.labels } : {},
11563
+ ...has(payload, "boundary") ? { boundary: payload?.boundary } : {}
11472
11564
  },
11473
11565
  activityContext(ctx, "webui", payload?.activityNote)
11474
11566
  );
@@ -11549,6 +11641,9 @@ async function handleKanbanRoute(ws, msg, ctx) {
11549
11641
  } : {},
11550
11642
  ...has(payload, "costCeilingUsd") ? {
11551
11643
  costCeilingUsd: payload?.costCeilingUsd === null || payload?.costCeilingUsd === "" ? null : Number(payload?.costCeilingUsd)
11644
+ } : {},
11645
+ ...has(payload, "boundary") ? {
11646
+ boundary: payload?.boundary ?? null
11552
11647
  } : {}
11553
11648
  },
11554
11649
  activityContext(ctx, "webui", payload?.activityNote)
@@ -12441,7 +12536,7 @@ var chronicleCache = /* @__PURE__ */ new Map();
12441
12536
  async function chronicleEngine(projectRoot) {
12442
12537
  const now = Date.now();
12443
12538
  const cached = chronicleCache.get(projectRoot);
12444
- if (cached && now - cached.loadedAt < 1e3) return cached.engine;
12539
+ if (cached && now - cached.loadedAt < 6e4) return cached.engine;
12445
12540
  const paths = resolveWstackPaths2({ projectRoot, userHome: os2.homedir() });
12446
12541
  const engine = await ChronicleQueryEngine.fromDirectory(
12447
12542
  path20.join(paths.projectDir, "chronicle")
@@ -12958,7 +13053,7 @@ function createMessageDispatcher(opts) {
12958
13053
  case "chronicle.query": {
12959
13054
  const payload = msg.payload ?? {};
12960
13055
  const engine = await chronicleEngine(state.getProjectRoot());
12961
- send(ws, { type: "chronicle.query_result", payload: engine.query(payload.query ?? {}) });
13056
+ send(ws, { type: "chronicle.query_result", payload: await engine.query(payload.query ?? {}) });
12962
13057
  break;
12963
13058
  }
12964
13059
  case "chronicle.facet": {
@@ -12988,7 +13083,7 @@ function createMessageDispatcher(opts) {
12988
13083
  type: "chronicle.facet_result",
12989
13084
  payload: {
12990
13085
  field: payload.field,
12991
- values: engine.facet(payload.field, payload.query ?? {}, payload.limit),
13086
+ values: await engine.facet(payload.field, payload.query ?? {}, payload.limit),
12992
13087
  diagnostics: engine.diagnostics
12993
13088
  }
12994
13089
  });
@@ -12999,7 +13094,7 @@ function createMessageDispatcher(opts) {
12999
13094
  const engine = await chronicleEngine(state.getProjectRoot());
13000
13095
  send(ws, {
13001
13096
  type: "chronicle.graph_result",
13002
- payload: engine.graph(payload.seed ?? {}, payload.hops, payload.maxNodes)
13097
+ payload: await engine.graph(payload.seed ?? {}, payload.hops, payload.maxNodes)
13003
13098
  });
13004
13099
  break;
13005
13100
  }
@@ -13054,9 +13149,9 @@ function createMessageDispatcher(opts) {
13054
13149
  }
13055
13150
 
13056
13151
  // src/server/pref-helpers.ts
13057
- import { atomicWrite as atomicWrite6, FORBIDDEN_PROTO_KEYS as FORBIDDEN_PROTO_KEYS2 } from "@wrongstack/core/utils";
13058
- import { decryptConfigSecrets as decryptConfigSecrets2, encryptConfigSecrets as encryptConfigSecrets2 } from "@wrongstack/core/security";
13059
13152
  import * as fs14 from "node:fs/promises";
13153
+ import { decryptConfigSecrets as decryptConfigSecrets2, encryptConfigSecrets as encryptConfigSecrets2 } from "@wrongstack/core/security";
13154
+ import { atomicWrite as atomicWrite6, FORBIDDEN_PROTO_KEYS as FORBIDDEN_PROTO_KEYS2 } from "@wrongstack/core/utils";
13060
13155
  var PREF_KEYS = [
13061
13156
  "autonomy",
13062
13157
  "autonomyDelayMs",
@@ -13101,6 +13196,7 @@ var PREF_KEYS = [
13101
13196
  "fallbackProfiles",
13102
13197
  "favoriteModels",
13103
13198
  "favoriteModelsOnly",
13199
+ "modelAvailabilitySchedule",
13104
13200
  "modelMatrix",
13105
13201
  "fallbackAuto",
13106
13202
  // Refiner + TUI visual prefs (parity with the CLI's embedded server —
@@ -13173,256 +13269,264 @@ async function updateGlobalConfig(deps2, holder, mutate, errorLabel) {
13173
13269
  try {
13174
13270
  await next;
13175
13271
  } catch (err) {
13176
- logger.warn(`${errorLabel}: failed to persist to config: ${err instanceof Error ? err.message : String(err)}`);
13272
+ logger.warn(
13273
+ `${errorLabel}: failed to persist to config: ${err instanceof Error ? err.message : String(err)}`
13274
+ );
13177
13275
  }
13178
13276
  }
13179
13277
  async function persistPrefsToConfig(deps2, holder, payload) {
13180
- return updateGlobalConfig(deps2, holder, (decrypted) => {
13181
- const autonomyCfg = decrypted.autonomy ?? {};
13182
- let autonomyTouched = false;
13183
- const setAutonomy = (key, val) => {
13184
- autonomyCfg[key] = val;
13185
- autonomyTouched = true;
13186
- };
13187
- if (typeof payload["autonomy"] === "string" && ["off", "suggest", "auto"].includes(payload["autonomy"])) {
13188
- setAutonomy("defaultMode", payload["autonomy"]);
13189
- }
13190
- if (typeof payload["autonomyDelayMs"] === "number")
13191
- setAutonomy("autoProceedDelayMs", payload["autonomyDelayMs"]);
13192
- if (typeof payload["autoProceedMaxIterations"] === "number")
13193
- setAutonomy("autoProceedMaxIterations", payload["autoProceedMaxIterations"]);
13194
- if (typeof payload["yolo"] === "boolean") {
13195
- setAutonomy("yolo", payload["yolo"]);
13196
- decrypted.yolo = payload["yolo"];
13197
- }
13198
- if (typeof payload["chime"] === "boolean") setAutonomy("chime", payload["chime"]);
13199
- if (typeof payload["confirmExit"] === "boolean")
13200
- setAutonomy("confirmExit", payload["confirmExit"]);
13201
- if (typeof payload["streamFleet"] === "boolean")
13202
- setAutonomy("streamFleet", payload["streamFleet"]);
13203
- if (typeof payload["enhanceEnabled"] === "boolean")
13204
- setAutonomy("enhance", payload["enhanceEnabled"]);
13205
- if (typeof payload["enhanceDelayMs"] === "number")
13206
- setAutonomy("enhanceDelayMs", payload["enhanceDelayMs"]);
13207
- if (typeof payload["enhanceLanguage"] === "string")
13208
- setAutonomy("enhanceLanguage", payload["enhanceLanguage"]);
13209
- if (typeof payload["refinerProvider"] === "string")
13210
- setAutonomy("refinerProvider", payload["refinerProvider"]);
13211
- if (typeof payload["refinerModel"] === "string")
13212
- setAutonomy("refinerModel", payload["refinerModel"]);
13213
- if (typeof payload["refinerFallbackProfile"] === "string")
13214
- setAutonomy("refinerFallbackProfile", payload["refinerFallbackProfile"]);
13215
- if (typeof payload["thinkingWord"] === "string")
13216
- setAutonomy("thinkingWord", payload["thinkingWord"]);
13217
- if (typeof payload["statuslineMode"] === "string")
13218
- setAutonomy("statuslineMode", payload["statuslineMode"]);
13219
- if (typeof payload["animationStyle"] === "string")
13220
- setAutonomy("animationStyle", payload["animationStyle"]);
13221
- if (typeof payload["showModelReasoning"] === "boolean")
13222
- setAutonomy("showModelReasoning", payload["showModelReasoning"]);
13223
- if (autonomyTouched) decrypted.autonomy = autonomyCfg;
13224
- if (typeof payload["nextPrediction"] === "boolean")
13225
- decrypted.nextPrediction = payload["nextPrediction"];
13226
- if (typeof payload["uiLocale"] === "string") decrypted.uiLocale = payload["uiLocale"];
13227
- if (Array.isArray(payload["fallbackModels"]))
13228
- decrypted.fallbackModels = payload["fallbackModels"];
13229
- if (payload["fallbackProfiles"] && typeof payload["fallbackProfiles"] === "object" && !Array.isArray(payload["fallbackProfiles"])) {
13230
- decrypted.fallbackProfiles = payload["fallbackProfiles"];
13231
- }
13232
- if (Array.isArray(payload["favoriteModels"]))
13233
- decrypted.favoriteModels = payload["favoriteModels"];
13234
- if (typeof payload["favoriteModelsOnly"] === "boolean")
13235
- decrypted.favoriteModelsOnly = payload["favoriteModelsOnly"];
13236
- if (payload["modelMatrix"] && typeof payload["modelMatrix"] === "object" && !Array.isArray(payload["modelMatrix"])) {
13237
- decrypted.modelMatrix = payload["modelMatrix"];
13238
- }
13239
- if (typeof payload["fallbackAuto"] === "boolean")
13240
- decrypted.fallbackAuto = payload["fallbackAuto"];
13241
- const FEATURE_MAP = {
13242
- featureMcp: "mcp",
13243
- featurePlugins: "plugins",
13244
- featureMemory: "memory",
13245
- featureSkills: "skills",
13246
- featureModelsRegistry: "modelsRegistry"
13247
- };
13248
- for (const [prefKey, cfgKey] of Object.entries(FEATURE_MAP)) {
13249
- if (typeof payload[prefKey] === "boolean") {
13250
- const feats = decrypted.features ?? {};
13251
- feats[cfgKey] = payload[prefKey];
13252
- decrypted.features = feats;
13253
- }
13254
- }
13255
- if (typeof payload["contextAutoCompact"] === "boolean" || typeof payload["contextStrategy"] === "string" || typeof payload["contextMode"] === "string") {
13256
- const ctxCfg = decrypted.context ?? {};
13257
- if (typeof payload["contextAutoCompact"] === "boolean")
13258
- ctxCfg.autoCompact = payload["contextAutoCompact"];
13259
- if (typeof payload["contextStrategy"] === "string")
13260
- ctxCfg.strategy = payload["contextStrategy"];
13261
- if (typeof payload["contextMode"] === "string") ctxCfg.mode = payload["contextMode"];
13262
- decrypted.context = ctxCfg;
13263
- }
13264
- if (typeof payload["tokenSavingTier"] === "string") {
13265
- const featsCfg = decrypted.features ?? {};
13266
- featsCfg.tokenSavingMode = payload["tokenSavingTier"];
13267
- decrypted.features = featsCfg;
13268
- }
13269
- if (typeof payload["maxConcurrent"] === "number") {
13270
- decrypted.maxConcurrent = payload["maxConcurrent"];
13271
- }
13272
- if (typeof payload["titleAnimation"] === "boolean") {
13273
- const autoCfg = decrypted.autonomy ?? {};
13274
- autoCfg.terminalTitleAnimation = payload["titleAnimation"];
13275
- decrypted.autonomy = autoCfg;
13276
- }
13277
- if (typeof payload["logLevel"] === "string") {
13278
- const logCfg = decrypted.log ?? {};
13279
- logCfg.level = payload["logLevel"];
13280
- decrypted.log = logCfg;
13281
- }
13282
- if (typeof payload["auditLevel"] === "string") {
13283
- const sessionCfg = decrypted.session ?? {};
13284
- sessionCfg.auditLevel = payload["auditLevel"];
13285
- decrypted.session = sessionCfg;
13286
- }
13287
- if (typeof payload["indexOnStart"] === "boolean") {
13288
- const indexingCfg = decrypted.indexing ?? {};
13289
- indexingCfg.onSessionStart = payload["indexOnStart"];
13290
- decrypted.indexing = indexingCfg;
13291
- }
13292
- if (typeof payload["maxIterations"] === "number") {
13293
- const toolsCfg = decrypted.tools ?? {};
13294
- toolsCfg.maxIterations = payload["maxIterations"];
13295
- decrypted.tools = toolsCfg;
13296
- }
13297
- const hqTouched = typeof payload["hqEnabled"] === "boolean" || typeof payload["hqUrl"] === "string" || typeof payload["hqToken"] === "string" || typeof payload["hqRawContent"] === "boolean";
13298
- if (hqTouched) {
13299
- const hqCfg = decrypted.hq ?? {};
13300
- if (typeof payload["hqEnabled"] === "boolean") hqCfg.enabled = payload["hqEnabled"];
13301
- if (typeof payload["hqUrl"] === "string") hqCfg.url = payload["hqUrl"];
13302
- if (typeof payload["hqToken"] === "string") hqCfg.token = payload["hqToken"];
13303
- if (typeof payload["hqRawContent"] === "boolean")
13304
- hqCfg.rawContent = payload["hqRawContent"];
13305
- decrypted.hq = hqCfg;
13306
- }
13307
- const tgTouched = typeof payload["tgSessionEnd"] === "boolean" || typeof payload["tgDelegate"] === "boolean" || typeof payload["tgLongToolMs"] === "number";
13308
- if (tgTouched) {
13309
- const ext = decrypted.extensions ?? {};
13310
- const tg = ext["telegram"] ?? {};
13311
- if (typeof payload["tgSessionEnd"] === "boolean") {
13312
- tg["notifyOnSessionEnd"] = payload["tgSessionEnd"];
13313
- }
13314
- if (typeof payload["tgDelegate"] === "boolean") {
13315
- tg["notifyOnDelegate"] = payload["tgDelegate"];
13316
- }
13317
- if (typeof payload["tgLongToolMs"] === "number") {
13318
- tg["longToolThresholdMs"] = payload["tgLongToolMs"];
13319
- }
13320
- ext["telegram"] = tg;
13321
- decrypted.extensions = ext;
13322
- }
13323
- const modelRuntimeTouched = typeof payload["reasoningMode"] === "string" || typeof payload["reasoningEffort"] === "string" || typeof payload["reasoningPreserve"] === "boolean" || typeof payload["cacheTtl"] === "string";
13324
- if (modelRuntimeTouched) {
13325
- const mr = decrypted.modelRuntime ?? {};
13326
- const reasoning = mr.reasoning ?? {};
13327
- if (typeof payload["reasoningMode"] === "string") reasoning.mode = payload["reasoningMode"];
13328
- if (typeof payload["reasoningEffort"] === "string")
13329
- reasoning.effort = payload["reasoningEffort"];
13330
- if (typeof payload["reasoningPreserve"] === "boolean")
13331
- reasoning.preserve = payload["reasoningPreserve"];
13332
- mr.reasoning = reasoning;
13333
- if (typeof payload["cacheTtl"] === "string" && payload["cacheTtl"] !== "default") {
13334
- mr.cache = { ttl: payload["cacheTtl"] };
13335
- } else if (payload["cacheTtl"] === "default") {
13336
- delete mr.cache;
13337
- }
13338
- decrypted.modelRuntime = mr;
13339
- }
13340
- if (typeof payload["breakerEnabled"] === "boolean" || typeof payload["breakerAutoKillResetMs"] === "number") {
13341
- const cb = decrypted.circuitBreaker ?? {};
13342
- if (typeof payload["breakerEnabled"] === "boolean") cb.enabled = payload["breakerEnabled"];
13343
- if (typeof payload["breakerAutoKillResetMs"] === "number")
13344
- cb.autoKillResetMs = payload["breakerAutoKillResetMs"];
13345
- decrypted.circuitBreaker = cb;
13346
- }
13347
- if (payload["fsAccess"] === "unrestricted" || payload["fsAccess"] === "project") {
13348
- const restrict = payload["fsAccess"] === "project";
13349
- const toolsCfg = decrypted.tools ?? {};
13350
- toolsCfg.restrictToProjectRoot = restrict;
13351
- decrypted.tools = toolsCfg;
13352
- const featsCfg = decrypted.features ?? {};
13353
- featsCfg.allowOutsideProjectRoot = !restrict;
13354
- decrypted.features = featsCfg;
13355
- }
13356
- if (typeof payload["debugStream"] === "boolean")
13357
- decrypted.debugStream = payload["debugStream"];
13358
- if (typeof payload["pluginsEnabled"] === "object" && payload["pluginsEnabled"] !== null) {
13359
- const ext = decrypted.extensions ?? {};
13360
- for (const [pluginName, enabled] of Object.entries(
13361
- payload["pluginsEnabled"]
13362
- )) {
13363
- if (FORBIDDEN_PROTO_KEYS2.has(pluginName)) continue;
13364
- const pExt = ext[pluginName] ?? {};
13365
- pExt["enabled"] = enabled;
13366
- ext[pluginName] = pExt;
13367
- }
13368
- decrypted.extensions = ext;
13369
- }
13370
- const chimeraTouched = typeof payload["chimeraEnabled"] === "boolean" || typeof payload["chimeraProvider"] === "string" || typeof payload["chimeraModel"] === "string" || typeof payload["chimeraMaxFiles"] === "number" || typeof payload["chimeraAutoFix"] === "string";
13371
- if (chimeraTouched) {
13372
- const ext = decrypted.extensions ?? {};
13373
- const chimera = ext["wstack-chimera"] ?? {};
13374
- if (typeof payload["chimeraEnabled"] === "boolean")
13375
- chimera["enabled"] = payload["chimeraEnabled"];
13376
- if (typeof payload["chimeraProvider"] === "string")
13377
- chimera["provider"] = payload["chimeraProvider"];
13378
- if (typeof payload["chimeraModel"] === "string")
13379
- chimera["model"] = payload["chimeraModel"];
13380
- if (typeof payload["chimeraMaxFiles"] === "number" && payload["chimeraMaxFiles"] >= 1) {
13381
- chimera["maxFiles"] = payload["chimeraMaxFiles"];
13382
- }
13383
- if (typeof payload["chimeraAutoFix"] === "string") {
13384
- if (payload["chimeraAutoFix"] === "off" || payload["chimeraAutoFix"] === "ask" || payload["chimeraAutoFix"] === "auto") {
13385
- chimera["autoFix"] = payload["chimeraAutoFix"];
13386
- }
13387
- }
13388
- ext["wstack-chimera"] = chimera;
13389
- decrypted.extensions = ext;
13390
- }
13391
- const autoReviewTouched = typeof payload["autoReviewEnabled"] === "boolean" || typeof payload["autoReviewProvider"] === "string" || typeof payload["autoReviewModel"] === "string" || typeof payload["autoReviewFallbackProfile"] === "string" || Array.isArray(payload["autoReviewFallbackModels"]) || typeof payload["autoReviewDebounceMs"] === "number" || typeof payload["autoReviewMaxFilesPerBatch"] === "number" || typeof payload["autoReviewMaxConcurrentReviews"] === "number" || typeof payload["autoReviewCascadeOn"] === "string";
13392
- if (autoReviewTouched) {
13393
- const ext = decrypted.extensions ?? {};
13394
- const ar = ext["wstack-auto-review"] ?? {};
13395
- if (typeof payload["autoReviewEnabled"] === "boolean")
13396
- ar["enabled"] = payload["autoReviewEnabled"];
13397
- if (typeof payload["autoReviewProvider"] === "string")
13398
- ar["provider"] = payload["autoReviewProvider"];
13399
- if (typeof payload["autoReviewModel"] === "string")
13400
- ar["model"] = payload["autoReviewModel"];
13401
- if (typeof payload["autoReviewFallbackProfile"] === "string") {
13402
- if (payload["autoReviewFallbackProfile"] === "") {
13403
- delete ar["fallbackProfile"];
13404
- } else {
13405
- ar["fallbackProfile"] = payload["autoReviewFallbackProfile"];
13406
- }
13278
+ return updateGlobalConfig(
13279
+ deps2,
13280
+ holder,
13281
+ (decrypted) => {
13282
+ const autonomyCfg = decrypted.autonomy ?? {};
13283
+ let autonomyTouched = false;
13284
+ const setAutonomy = (key, val) => {
13285
+ autonomyCfg[key] = val;
13286
+ autonomyTouched = true;
13287
+ };
13288
+ if (typeof payload["autonomy"] === "string" && ["off", "suggest", "auto"].includes(payload["autonomy"])) {
13289
+ setAutonomy("defaultMode", payload["autonomy"]);
13407
13290
  }
13408
- if (typeof payload["autoReviewDebounceMs"] === "number" && payload["autoReviewDebounceMs"] >= 0) {
13409
- ar["debounceMs"] = payload["autoReviewDebounceMs"];
13291
+ if (typeof payload["autonomyDelayMs"] === "number")
13292
+ setAutonomy("autoProceedDelayMs", payload["autonomyDelayMs"]);
13293
+ if (typeof payload["autoProceedMaxIterations"] === "number")
13294
+ setAutonomy("autoProceedMaxIterations", payload["autoProceedMaxIterations"]);
13295
+ if (typeof payload["yolo"] === "boolean") {
13296
+ setAutonomy("yolo", payload["yolo"]);
13297
+ decrypted.yolo = payload["yolo"];
13298
+ }
13299
+ if (typeof payload["chime"] === "boolean") setAutonomy("chime", payload["chime"]);
13300
+ if (typeof payload["confirmExit"] === "boolean")
13301
+ setAutonomy("confirmExit", payload["confirmExit"]);
13302
+ if (typeof payload["streamFleet"] === "boolean")
13303
+ setAutonomy("streamFleet", payload["streamFleet"]);
13304
+ if (typeof payload["enhanceEnabled"] === "boolean")
13305
+ setAutonomy("enhance", payload["enhanceEnabled"]);
13306
+ if (typeof payload["enhanceDelayMs"] === "number")
13307
+ setAutonomy("enhanceDelayMs", payload["enhanceDelayMs"]);
13308
+ if (typeof payload["enhanceLanguage"] === "string")
13309
+ setAutonomy("enhanceLanguage", payload["enhanceLanguage"]);
13310
+ if (typeof payload["refinerProvider"] === "string")
13311
+ setAutonomy("refinerProvider", payload["refinerProvider"]);
13312
+ if (typeof payload["refinerModel"] === "string")
13313
+ setAutonomy("refinerModel", payload["refinerModel"]);
13314
+ if (typeof payload["refinerFallbackProfile"] === "string")
13315
+ setAutonomy("refinerFallbackProfile", payload["refinerFallbackProfile"]);
13316
+ if (typeof payload["thinkingWord"] === "string")
13317
+ setAutonomy("thinkingWord", payload["thinkingWord"]);
13318
+ if (typeof payload["statuslineMode"] === "string")
13319
+ setAutonomy("statuslineMode", payload["statuslineMode"]);
13320
+ if (typeof payload["animationStyle"] === "string")
13321
+ setAutonomy("animationStyle", payload["animationStyle"]);
13322
+ if (typeof payload["showModelReasoning"] === "boolean")
13323
+ setAutonomy("showModelReasoning", payload["showModelReasoning"]);
13324
+ if (autonomyTouched) decrypted.autonomy = autonomyCfg;
13325
+ if (typeof payload["nextPrediction"] === "boolean")
13326
+ decrypted.nextPrediction = payload["nextPrediction"];
13327
+ if (typeof payload["uiLocale"] === "string") decrypted.uiLocale = payload["uiLocale"];
13328
+ if (Array.isArray(payload["fallbackModels"]))
13329
+ decrypted.fallbackModels = payload["fallbackModels"];
13330
+ if (payload["fallbackProfiles"] && typeof payload["fallbackProfiles"] === "object" && !Array.isArray(payload["fallbackProfiles"])) {
13331
+ decrypted.fallbackProfiles = payload["fallbackProfiles"];
13410
13332
  }
13411
- if (typeof payload["autoReviewMaxFilesPerBatch"] === "number" && payload["autoReviewMaxFilesPerBatch"] >= 1) {
13412
- ar["maxFilesPerBatch"] = payload["autoReviewMaxFilesPerBatch"];
13333
+ if (Array.isArray(payload["favoriteModels"]))
13334
+ decrypted.favoriteModels = payload["favoriteModels"];
13335
+ if (typeof payload["favoriteModelsOnly"] === "boolean")
13336
+ decrypted.favoriteModelsOnly = payload["favoriteModelsOnly"];
13337
+ if (Array.isArray(payload["modelAvailabilitySchedule"]))
13338
+ decrypted.modelAvailabilitySchedule = payload["modelAvailabilitySchedule"];
13339
+ if (payload["modelMatrix"] && typeof payload["modelMatrix"] === "object" && !Array.isArray(payload["modelMatrix"])) {
13340
+ decrypted.modelMatrix = payload["modelMatrix"];
13341
+ }
13342
+ if (typeof payload["fallbackAuto"] === "boolean")
13343
+ decrypted.fallbackAuto = payload["fallbackAuto"];
13344
+ const FEATURE_MAP = {
13345
+ featureMcp: "mcp",
13346
+ featurePlugins: "plugins",
13347
+ featureMemory: "memory",
13348
+ featureSkills: "skills",
13349
+ featureModelsRegistry: "modelsRegistry"
13350
+ };
13351
+ for (const [prefKey, cfgKey] of Object.entries(FEATURE_MAP)) {
13352
+ if (typeof payload[prefKey] === "boolean") {
13353
+ const feats = decrypted.features ?? {};
13354
+ feats[cfgKey] = payload[prefKey];
13355
+ decrypted.features = feats;
13356
+ }
13357
+ }
13358
+ if (typeof payload["contextAutoCompact"] === "boolean" || typeof payload["contextStrategy"] === "string" || typeof payload["contextMode"] === "string") {
13359
+ const ctxCfg = decrypted.context ?? {};
13360
+ if (typeof payload["contextAutoCompact"] === "boolean")
13361
+ ctxCfg.autoCompact = payload["contextAutoCompact"];
13362
+ if (typeof payload["contextStrategy"] === "string")
13363
+ ctxCfg.strategy = payload["contextStrategy"];
13364
+ if (typeof payload["contextMode"] === "string") ctxCfg.mode = payload["contextMode"];
13365
+ decrypted.context = ctxCfg;
13366
+ }
13367
+ if (typeof payload["tokenSavingTier"] === "string") {
13368
+ const featsCfg = decrypted.features ?? {};
13369
+ featsCfg.tokenSavingMode = payload["tokenSavingTier"];
13370
+ decrypted.features = featsCfg;
13371
+ }
13372
+ if (typeof payload["maxConcurrent"] === "number") {
13373
+ decrypted.maxConcurrent = payload["maxConcurrent"];
13374
+ }
13375
+ if (typeof payload["titleAnimation"] === "boolean") {
13376
+ const autoCfg = decrypted.autonomy ?? {};
13377
+ autoCfg.terminalTitleAnimation = payload["titleAnimation"];
13378
+ decrypted.autonomy = autoCfg;
13413
13379
  }
13414
- if (typeof payload["autoReviewMaxConcurrentReviews"] === "number" && payload["autoReviewMaxConcurrentReviews"] >= 1) {
13415
- ar["maxConcurrentReviews"] = payload["autoReviewMaxConcurrentReviews"];
13380
+ if (typeof payload["logLevel"] === "string") {
13381
+ const logCfg = decrypted.log ?? {};
13382
+ logCfg.level = payload["logLevel"];
13383
+ decrypted.log = logCfg;
13384
+ }
13385
+ if (typeof payload["auditLevel"] === "string") {
13386
+ const sessionCfg = decrypted.session ?? {};
13387
+ sessionCfg.auditLevel = payload["auditLevel"];
13388
+ decrypted.session = sessionCfg;
13389
+ }
13390
+ if (typeof payload["indexOnStart"] === "boolean") {
13391
+ const indexingCfg = decrypted.indexing ?? {};
13392
+ indexingCfg.onSessionStart = payload["indexOnStart"];
13393
+ decrypted.indexing = indexingCfg;
13394
+ }
13395
+ if (typeof payload["maxIterations"] === "number") {
13396
+ const toolsCfg = decrypted.tools ?? {};
13397
+ toolsCfg.maxIterations = payload["maxIterations"];
13398
+ decrypted.tools = toolsCfg;
13399
+ }
13400
+ const hqTouched = typeof payload["hqEnabled"] === "boolean" || typeof payload["hqUrl"] === "string" || typeof payload["hqToken"] === "string" || typeof payload["hqRawContent"] === "boolean";
13401
+ if (hqTouched) {
13402
+ const hqCfg = decrypted.hq ?? {};
13403
+ if (typeof payload["hqEnabled"] === "boolean") hqCfg.enabled = payload["hqEnabled"];
13404
+ if (typeof payload["hqUrl"] === "string") hqCfg.url = payload["hqUrl"];
13405
+ if (typeof payload["hqToken"] === "string") hqCfg.token = payload["hqToken"];
13406
+ if (typeof payload["hqRawContent"] === "boolean")
13407
+ hqCfg.rawContent = payload["hqRawContent"];
13408
+ decrypted.hq = hqCfg;
13409
+ }
13410
+ const tgTouched = typeof payload["tgSessionEnd"] === "boolean" || typeof payload["tgDelegate"] === "boolean" || typeof payload["tgLongToolMs"] === "number";
13411
+ if (tgTouched) {
13412
+ const ext = decrypted.extensions ?? {};
13413
+ const tg = ext["telegram"] ?? {};
13414
+ if (typeof payload["tgSessionEnd"] === "boolean") {
13415
+ tg["notifyOnSessionEnd"] = payload["tgSessionEnd"];
13416
+ }
13417
+ if (typeof payload["tgDelegate"] === "boolean") {
13418
+ tg["notifyOnDelegate"] = payload["tgDelegate"];
13419
+ }
13420
+ if (typeof payload["tgLongToolMs"] === "number") {
13421
+ tg["longToolThresholdMs"] = payload["tgLongToolMs"];
13422
+ }
13423
+ ext["telegram"] = tg;
13424
+ decrypted.extensions = ext;
13425
+ }
13426
+ const modelRuntimeTouched = typeof payload["reasoningMode"] === "string" || typeof payload["reasoningEffort"] === "string" || typeof payload["reasoningPreserve"] === "boolean" || typeof payload["cacheTtl"] === "string";
13427
+ if (modelRuntimeTouched) {
13428
+ const mr = decrypted.modelRuntime ?? {};
13429
+ const reasoning = mr.reasoning ?? {};
13430
+ if (typeof payload["reasoningMode"] === "string") reasoning.mode = payload["reasoningMode"];
13431
+ if (typeof payload["reasoningEffort"] === "string")
13432
+ reasoning.effort = payload["reasoningEffort"];
13433
+ if (typeof payload["reasoningPreserve"] === "boolean")
13434
+ reasoning.preserve = payload["reasoningPreserve"];
13435
+ mr.reasoning = reasoning;
13436
+ if (typeof payload["cacheTtl"] === "string" && payload["cacheTtl"] !== "default") {
13437
+ mr.cache = { ttl: payload["cacheTtl"] };
13438
+ } else if (payload["cacheTtl"] === "default") {
13439
+ delete mr.cache;
13440
+ }
13441
+ decrypted.modelRuntime = mr;
13416
13442
  }
13417
- if (typeof payload["autoReviewCascadeOn"] === "string") {
13418
- if (payload["autoReviewCascadeOn"] === "off" || payload["autoReviewCascadeOn"] === "critical" || payload["autoReviewCascadeOn"] === "high") {
13419
- ar["cascadeOn"] = payload["autoReviewCascadeOn"];
13443
+ if (typeof payload["breakerEnabled"] === "boolean" || typeof payload["breakerAutoKillResetMs"] === "number") {
13444
+ const cb = decrypted.circuitBreaker ?? {};
13445
+ if (typeof payload["breakerEnabled"] === "boolean") cb.enabled = payload["breakerEnabled"];
13446
+ if (typeof payload["breakerAutoKillResetMs"] === "number")
13447
+ cb.autoKillResetMs = payload["breakerAutoKillResetMs"];
13448
+ decrypted.circuitBreaker = cb;
13449
+ }
13450
+ if (payload["fsAccess"] === "unrestricted" || payload["fsAccess"] === "project") {
13451
+ const restrict = payload["fsAccess"] === "project";
13452
+ const toolsCfg = decrypted.tools ?? {};
13453
+ toolsCfg.restrictToProjectRoot = restrict;
13454
+ decrypted.tools = toolsCfg;
13455
+ const featsCfg = decrypted.features ?? {};
13456
+ featsCfg.allowOutsideProjectRoot = !restrict;
13457
+ decrypted.features = featsCfg;
13458
+ }
13459
+ if (typeof payload["debugStream"] === "boolean")
13460
+ decrypted.debugStream = payload["debugStream"];
13461
+ if (typeof payload["pluginsEnabled"] === "object" && payload["pluginsEnabled"] !== null) {
13462
+ const ext = decrypted.extensions ?? {};
13463
+ for (const [pluginName, enabled] of Object.entries(
13464
+ payload["pluginsEnabled"]
13465
+ )) {
13466
+ if (FORBIDDEN_PROTO_KEYS2.has(pluginName)) continue;
13467
+ const pExt = ext[pluginName] ?? {};
13468
+ pExt["enabled"] = enabled;
13469
+ ext[pluginName] = pExt;
13470
+ }
13471
+ decrypted.extensions = ext;
13472
+ }
13473
+ const chimeraTouched = typeof payload["chimeraEnabled"] === "boolean" || typeof payload["chimeraProvider"] === "string" || typeof payload["chimeraModel"] === "string" || typeof payload["chimeraMaxFiles"] === "number" || typeof payload["chimeraAutoFix"] === "string";
13474
+ if (chimeraTouched) {
13475
+ const ext = decrypted.extensions ?? {};
13476
+ const chimera = ext["wstack-chimera"] ?? {};
13477
+ if (typeof payload["chimeraEnabled"] === "boolean")
13478
+ chimera["enabled"] = payload["chimeraEnabled"];
13479
+ if (typeof payload["chimeraProvider"] === "string")
13480
+ chimera["provider"] = payload["chimeraProvider"];
13481
+ if (typeof payload["chimeraModel"] === "string") chimera["model"] = payload["chimeraModel"];
13482
+ if (typeof payload["chimeraMaxFiles"] === "number" && payload["chimeraMaxFiles"] >= 1) {
13483
+ chimera["maxFiles"] = payload["chimeraMaxFiles"];
13484
+ }
13485
+ if (typeof payload["chimeraAutoFix"] === "string") {
13486
+ if (payload["chimeraAutoFix"] === "off" || payload["chimeraAutoFix"] === "ask" || payload["chimeraAutoFix"] === "auto") {
13487
+ chimera["autoFix"] = payload["chimeraAutoFix"];
13488
+ }
13489
+ }
13490
+ ext["wstack-chimera"] = chimera;
13491
+ decrypted.extensions = ext;
13492
+ }
13493
+ const autoReviewTouched = typeof payload["autoReviewEnabled"] === "boolean" || typeof payload["autoReviewProvider"] === "string" || typeof payload["autoReviewModel"] === "string" || typeof payload["autoReviewFallbackProfile"] === "string" || Array.isArray(payload["autoReviewFallbackModels"]) || typeof payload["autoReviewDebounceMs"] === "number" || typeof payload["autoReviewMaxFilesPerBatch"] === "number" || typeof payload["autoReviewMaxConcurrentReviews"] === "number" || typeof payload["autoReviewCascadeOn"] === "string";
13494
+ if (autoReviewTouched) {
13495
+ const ext = decrypted.extensions ?? {};
13496
+ const ar = ext["wstack-auto-review"] ?? {};
13497
+ if (typeof payload["autoReviewEnabled"] === "boolean")
13498
+ ar["enabled"] = payload["autoReviewEnabled"];
13499
+ if (typeof payload["autoReviewProvider"] === "string")
13500
+ ar["provider"] = payload["autoReviewProvider"];
13501
+ if (typeof payload["autoReviewModel"] === "string")
13502
+ ar["model"] = payload["autoReviewModel"];
13503
+ if (typeof payload["autoReviewFallbackProfile"] === "string") {
13504
+ if (payload["autoReviewFallbackProfile"] === "") {
13505
+ delete ar["fallbackProfile"];
13506
+ } else {
13507
+ ar["fallbackProfile"] = payload["autoReviewFallbackProfile"];
13508
+ }
13509
+ }
13510
+ if (typeof payload["autoReviewDebounceMs"] === "number" && payload["autoReviewDebounceMs"] >= 0) {
13511
+ ar["debounceMs"] = payload["autoReviewDebounceMs"];
13512
+ }
13513
+ if (typeof payload["autoReviewMaxFilesPerBatch"] === "number" && payload["autoReviewMaxFilesPerBatch"] >= 1) {
13514
+ ar["maxFilesPerBatch"] = payload["autoReviewMaxFilesPerBatch"];
13515
+ }
13516
+ if (typeof payload["autoReviewMaxConcurrentReviews"] === "number" && payload["autoReviewMaxConcurrentReviews"] >= 1) {
13517
+ ar["maxConcurrentReviews"] = payload["autoReviewMaxConcurrentReviews"];
13518
+ }
13519
+ if (typeof payload["autoReviewCascadeOn"] === "string") {
13520
+ if (payload["autoReviewCascadeOn"] === "off" || payload["autoReviewCascadeOn"] === "critical" || payload["autoReviewCascadeOn"] === "high") {
13521
+ ar["cascadeOn"] = payload["autoReviewCascadeOn"];
13522
+ }
13420
13523
  }
13524
+ ext["wstack-auto-review"] = ar;
13525
+ decrypted.extensions = ext;
13421
13526
  }
13422
- ext["wstack-auto-review"] = ar;
13423
- decrypted.extensions = ext;
13424
- }
13425
- }, "prefs");
13527
+ },
13528
+ "prefs"
13529
+ );
13426
13530
  }
13427
13531
 
13428
13532
  // src/server/provider-handlers.ts
@@ -13760,6 +13864,7 @@ import {
13760
13864
  gatedEnhancerReasoning,
13761
13865
  nextEnhanceTimeout,
13762
13866
  recentTextTurns,
13867
+ resolveConfiguredRefinerRef,
13763
13868
  resolveEnhanceFallbackRef,
13764
13869
  resolveProviderModelList
13765
13870
  } from "@wrongstack/core";
@@ -14622,6 +14727,26 @@ function buildRoutes(state, deps2, cb) {
14622
14727
  });
14623
14728
  return;
14624
14729
  }
14730
+ } else {
14731
+ const configuredRef = resolveConfiguredRefinerRef({
14732
+ ...cfg,
14733
+ provider: providerId,
14734
+ model
14735
+ });
14736
+ if (configuredRef) {
14737
+ const slash = configuredRef.indexOf("/");
14738
+ const configuredProvider = slash > 0 ? configuredRef.slice(0, slash) : providerId;
14739
+ const configuredModel = slash > 0 ? configuredRef.slice(slash + 1) : configuredRef;
14740
+ try {
14741
+ const providerCfg = cfg.providers?.[configuredProvider] ?? {
14742
+ type: configuredProvider
14743
+ };
14744
+ provider = deps2.providerRegistry.has(configuredProvider) ? deps2.providerRegistry.create({ ...providerCfg, type: configuredProvider }) : makeProviderFromConfig2(configuredProvider, providerCfg);
14745
+ providerId = configuredProvider;
14746
+ model = configuredModel;
14747
+ } catch {
14748
+ }
14749
+ }
14625
14750
  }
14626
14751
  const baseTimeout = 9e4;
14627
14752
  const timeoutMs = typeof payload.timeoutMs === "number" && payload.timeoutMs > 0 ? payload.timeoutMs : baseTimeout;
@@ -14808,19 +14933,27 @@ function buildRoutes(state, deps2, cb) {
14808
14933
  cfg.favoriteModels = payload["favoriteModels"];
14809
14934
  if (typeof payload["favoriteModelsOnly"] === "boolean")
14810
14935
  cfg.favoriteModelsOnly = payload["favoriteModelsOnly"];
14936
+ if (Array.isArray(payload["modelAvailabilitySchedule"]))
14937
+ cfg.modelAvailabilitySchedule = payload["modelAvailabilitySchedule"];
14811
14938
  if (payload["modelMatrix"] && typeof payload["modelMatrix"] === "object" && !Array.isArray(payload["modelMatrix"])) {
14812
14939
  cfg.modelMatrix = payload["modelMatrix"];
14813
14940
  }
14814
14941
  if (typeof payload["fallbackAuto"] === "boolean") cfg.fallbackAuto = payload["fallbackAuto"];
14815
14942
  const routingPatch = {};
14816
- if (Array.isArray(payload["fallbackModels"])) routingPatch.fallbackModels = payload["fallbackModels"];
14943
+ if (Array.isArray(payload["fallbackModels"]))
14944
+ routingPatch.fallbackModels = payload["fallbackModels"];
14817
14945
  if (payload["fallbackProfiles"] && typeof payload["fallbackProfiles"] === "object" && !Array.isArray(payload["fallbackProfiles"]))
14818
14946
  routingPatch.fallbackProfiles = payload["fallbackProfiles"];
14819
- if (Array.isArray(payload["favoriteModels"])) routingPatch.favoriteModels = payload["favoriteModels"];
14820
- if (typeof payload["favoriteModelsOnly"] === "boolean") routingPatch.favoriteModelsOnly = payload["favoriteModelsOnly"];
14947
+ if (Array.isArray(payload["favoriteModels"]))
14948
+ routingPatch.favoriteModels = payload["favoriteModels"];
14949
+ if (typeof payload["favoriteModelsOnly"] === "boolean")
14950
+ routingPatch.favoriteModelsOnly = payload["favoriteModelsOnly"];
14951
+ if (Array.isArray(payload["modelAvailabilitySchedule"]))
14952
+ routingPatch.modelAvailabilitySchedule = payload["modelAvailabilitySchedule"];
14821
14953
  if (payload["modelMatrix"] && typeof payload["modelMatrix"] === "object" && !Array.isArray(payload["modelMatrix"]))
14822
14954
  routingPatch.modelMatrix = payload["modelMatrix"];
14823
- if (typeof payload["fallbackAuto"] === "boolean") routingPatch.fallbackAuto = payload["fallbackAuto"];
14955
+ if (typeof payload["fallbackAuto"] === "boolean")
14956
+ routingPatch.fallbackAuto = payload["fallbackAuto"];
14824
14957
  if (Object.keys(routingPatch).length > 0)
14825
14958
  deps2.configStore.update(routingPatch);
14826
14959
  if (typeof payload["contextAutoCompact"] === "boolean") {
@@ -15744,6 +15877,7 @@ export {
15744
15877
  normalizeCodeMapFileTarget,
15745
15878
  normalizeKeys,
15746
15879
  openBrowser,
15880
+ paginateKanbanBoards,
15747
15881
  patchConfig,
15748
15882
  persistPrefsToConfig,
15749
15883
  projectSavedProviders,