@wrongstack/webui-server 0.289.0 → 0.291.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 +542 -335
- package/dist/index.js.map +3 -3
- package/dist/server/backend-services.d.ts +2 -2
- package/dist/server/backend-services.d.ts.map +1 -1
- package/dist/server/context-meta.d.ts.map +1 -1
- package/dist/server/entry.js +540 -335
- package/dist/server/entry.js.map +3 -3
- package/dist/server/handlers.js.map +2 -2
- package/dist/server/http-server.d.ts.map +1 -1
- package/dist/server/index.d.ts +3 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/kanban-routes.d.ts +15 -0
- package/dist/server/kanban-routes.d.ts.map +1 -1
- package/dist/server/memory-handlers.d.ts +13 -0
- package/dist/server/memory-handlers.d.ts.map +1 -1
- package/dist/server/message-dispatcher.d.ts +3 -2
- package/dist/server/message-dispatcher.d.ts.map +1 -1
- package/dist/server/pending-confirms.d.ts +1 -0
- package/dist/server/pending-confirms.d.ts.map +1 -1
- package/dist/server/pre-context-services.d.ts +3 -2
- package/dist/server/pre-context-services.d.ts.map +1 -1
- package/dist/server/pref-helpers.d.ts +22 -8
- package/dist/server/pref-helpers.d.ts.map +1 -1
- package/dist/server/provider-config-io.d.ts +2 -1
- package/dist/server/provider-config-io.d.ts.map +1 -1
- package/dist/server/provider-handlers.d.ts +2 -0
- package/dist/server/provider-handlers.d.ts.map +1 -1
- package/dist/server/routes.d.ts +2 -2
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/server-runtime.d.ts +5 -20
- package/dist/server/server-runtime.d.ts.map +1 -1
- package/dist/server/setup-events.d.ts.map +1 -1
- package/dist/server/start-webui.d.ts.map +1 -1
- package/dist/server/terminal-ws-handler.d.ts +2 -1
- package/dist/server/terminal-ws-handler.d.ts.map +1 -1
- package/dist/server/ws-payload-validation.d.ts +24 -23
- package/dist/server/ws-payload-validation.d.ts.map +1 -1
- package/package.json +12 -12
package/dist/server/entry.js
CHANGED
|
@@ -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
|
|
1817
|
-
if (
|
|
1816
|
+
let path24 = m[3] ?? "";
|
|
1817
|
+
if (path24 === "") {
|
|
1818
1818
|
i += 1;
|
|
1819
|
-
|
|
1819
|
+
path24 = parts[i + 1] ?? parts[i] ?? "";
|
|
1820
1820
|
i += 1;
|
|
1821
1821
|
}
|
|
1822
|
-
if (!
|
|
1823
|
-
const prev = counts.get(
|
|
1824
|
-
counts.set(
|
|
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
|
|
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(
|
|
1849
|
-
let deleted = counts.get(
|
|
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:
|
|
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,
|
|
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:
|
|
1868
|
-
if (!
|
|
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:${
|
|
1876
|
+
const oldText = await git(["show", `HEAD:${path24}`]);
|
|
1877
1877
|
let newText = "";
|
|
1878
1878
|
try {
|
|
1879
|
-
const abs = cwd ? join14(cwd,
|
|
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 });
|
|
@@ -1908,6 +1908,7 @@ async function handleGitDiff(ws, projectRoot, path23) {
|
|
|
1908
1908
|
import * as fs6 from "node:fs/promises";
|
|
1909
1909
|
import * as http from "node:http";
|
|
1910
1910
|
import * as path7 from "node:path";
|
|
1911
|
+
import * as v8 from "node:v8";
|
|
1911
1912
|
|
|
1912
1913
|
// src/server/http-server/api-handlers.ts
|
|
1913
1914
|
async function handleApiSessions(res, globalRoot) {
|
|
@@ -3206,6 +3207,23 @@ function createHttpServer(opts) {
|
|
|
3206
3207
|
}
|
|
3207
3208
|
return;
|
|
3208
3209
|
}
|
|
3210
|
+
if (url.pathname === "/debug/system" && req.method === "GET") {
|
|
3211
|
+
res.writeHead(200, {
|
|
3212
|
+
"Content-Type": "application/json",
|
|
3213
|
+
"Cache-Control": "no-store"
|
|
3214
|
+
});
|
|
3215
|
+
res.end(
|
|
3216
|
+
JSON.stringify({
|
|
3217
|
+
pid: process.pid,
|
|
3218
|
+
memoryUsage: process.memoryUsage(),
|
|
3219
|
+
heapLimit: v8.getHeapStatistics().heap_size_limit,
|
|
3220
|
+
uptime: process.uptime(),
|
|
3221
|
+
cpuUsage: process.cpuUsage(),
|
|
3222
|
+
timestamp: Date.now()
|
|
3223
|
+
})
|
|
3224
|
+
);
|
|
3225
|
+
return;
|
|
3226
|
+
}
|
|
3209
3227
|
let filePath;
|
|
3210
3228
|
if (url.pathname === "/" || url.pathname === "") {
|
|
3211
3229
|
filePath = path7.join(distDir, "index.html");
|
|
@@ -3732,6 +3750,44 @@ async function handleSuperMemoryList(ws, memoryStore) {
|
|
|
3732
3750
|
send(ws, { type: "memory.super.list", payload: { error: errMessage(err) } });
|
|
3733
3751
|
}
|
|
3734
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
|
+
}
|
|
3735
3791
|
async function handleSuperMemoryGet(ws, msg, memoryStore) {
|
|
3736
3792
|
if (!isSuperMemoryStore(memoryStore)) {
|
|
3737
3793
|
send(ws, { type: "memory.super.get", payload: { error: requiresSuperMemory("memory.super.get") } });
|
|
@@ -4281,7 +4337,7 @@ async function loadSavedProviders(configPath, vault) {
|
|
|
4281
4337
|
if (!parsed.providers) return {};
|
|
4282
4338
|
return decryptConfigSecrets(parsed.providers, vault);
|
|
4283
4339
|
}
|
|
4284
|
-
async function saveProviders(configPath, vault, providers) {
|
|
4340
|
+
async function saveProviders(configPath, vault, providers, profileConfigPath) {
|
|
4285
4341
|
let raw;
|
|
4286
4342
|
let fileExists = true;
|
|
4287
4343
|
try {
|
|
@@ -4315,6 +4371,23 @@ async function saveProviders(configPath, vault, providers) {
|
|
|
4315
4371
|
parsed.providers = providers;
|
|
4316
4372
|
const encrypted = encryptConfigSecrets(parsed, vault);
|
|
4317
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
|
+
}
|
|
4318
4391
|
}
|
|
4319
4392
|
|
|
4320
4393
|
// src/server/provider-keys.ts
|
|
@@ -5164,6 +5237,7 @@ var BOOLEAN_PREF_KEYS = /* @__PURE__ */ new Set([
|
|
|
5164
5237
|
"hqRawContent",
|
|
5165
5238
|
"fallbackAuto",
|
|
5166
5239
|
"favoriteModelsOnly",
|
|
5240
|
+
"modelAvailabilitySchedule",
|
|
5167
5241
|
"breakerEnabled",
|
|
5168
5242
|
"debugStream",
|
|
5169
5243
|
// Chimera + auto-review master toggles
|
|
@@ -5228,34 +5302,34 @@ var ENUM_PREF_KEYS = {
|
|
|
5228
5302
|
chimeraAutoFix: /* @__PURE__ */ new Set(["off", "ask", "auto"]),
|
|
5229
5303
|
autoReviewCascadeOn: /* @__PURE__ */ new Set(["off", "critical", "high"])
|
|
5230
5304
|
};
|
|
5231
|
-
function validateModelRuntimeValue(modelRuntime,
|
|
5305
|
+
function validateModelRuntimeValue(modelRuntime, path24) {
|
|
5232
5306
|
const reasoning = modelRuntime["reasoning"];
|
|
5233
5307
|
if (reasoning !== void 0) {
|
|
5234
|
-
if (!isRecord(reasoning)) return `${
|
|
5308
|
+
if (!isRecord(reasoning)) return `${path24}.reasoning must be an object when provided`;
|
|
5235
5309
|
const mode = reasoning["mode"];
|
|
5236
5310
|
const effort = reasoning["effort"];
|
|
5237
5311
|
const preserve = reasoning["preserve"];
|
|
5238
5312
|
if (mode !== void 0 && (typeof mode !== "string" || !REASONING_MODE_VALUES.has(mode))) {
|
|
5239
|
-
return `${
|
|
5313
|
+
return `${path24}.reasoning.mode must be one of: ${Array.from(REASONING_MODE_VALUES).join(", ")}`;
|
|
5240
5314
|
}
|
|
5241
5315
|
if (effort !== void 0 && (typeof effort !== "string" || !REASONING_EFFORT_VALUES.has(effort))) {
|
|
5242
|
-
return `${
|
|
5316
|
+
return `${path24}.reasoning.effort must be one of: ${Array.from(REASONING_EFFORT_VALUES).join(", ")}`;
|
|
5243
5317
|
}
|
|
5244
5318
|
if (preserve !== void 0 && typeof preserve !== "boolean") {
|
|
5245
|
-
return `${
|
|
5319
|
+
return `${path24}.reasoning.preserve must be a boolean when provided`;
|
|
5246
5320
|
}
|
|
5247
5321
|
}
|
|
5248
5322
|
const cache = modelRuntime["cache"];
|
|
5249
5323
|
if (cache !== void 0) {
|
|
5250
|
-
if (!isRecord(cache)) return `${
|
|
5324
|
+
if (!isRecord(cache)) return `${path24}.cache must be an object when provided`;
|
|
5251
5325
|
const ttl = cache["ttl"];
|
|
5252
5326
|
if (ttl !== void 0 && (typeof ttl !== "string" || !CACHE_TTL_VALUES.has(ttl) || ttl === "default")) {
|
|
5253
|
-
return `${
|
|
5327
|
+
return `${path24}.cache.ttl must be one of: 5m, 1h`;
|
|
5254
5328
|
}
|
|
5255
5329
|
}
|
|
5256
5330
|
const parameters = modelRuntime["parameters"];
|
|
5257
5331
|
if (parameters !== void 0 && !isRecord(parameters)) {
|
|
5258
|
-
return `${
|
|
5332
|
+
return `${path24}.parameters must be an object when provided`;
|
|
5259
5333
|
}
|
|
5260
5334
|
return null;
|
|
5261
5335
|
}
|
|
@@ -5308,7 +5382,10 @@ function validatePreferenceValue(key, value) {
|
|
|
5308
5382
|
return `prefs.update payload.${key}.modelRuntime must be an object when provided`;
|
|
5309
5383
|
}
|
|
5310
5384
|
if (isRecord(modelRuntime)) {
|
|
5311
|
-
const runtimeError = validateModelRuntimeValue(
|
|
5385
|
+
const runtimeError = validateModelRuntimeValue(
|
|
5386
|
+
modelRuntime,
|
|
5387
|
+
`prefs.update payload.${key}.modelRuntime`
|
|
5388
|
+
);
|
|
5312
5389
|
if (runtimeError) return runtimeError;
|
|
5313
5390
|
}
|
|
5314
5391
|
if (model === void 0 && fallbackProfile === void 0 && modelRuntime === void 0) {
|
|
@@ -5545,8 +5622,8 @@ function validateShellOpenPayload(payload) {
|
|
|
5545
5622
|
if (!isRecord(payload)) {
|
|
5546
5623
|
return { ok: false, message: "shell.open payload must be an object with string path" };
|
|
5547
5624
|
}
|
|
5548
|
-
const
|
|
5549
|
-
if (typeof
|
|
5625
|
+
const path24 = payload["path"];
|
|
5626
|
+
if (typeof path24 !== "string" || path24.trim().length === 0) {
|
|
5550
5627
|
return { ok: false, message: "shell.open payload.path must be a non-empty string" };
|
|
5551
5628
|
}
|
|
5552
5629
|
const target = payload["target"];
|
|
@@ -5559,7 +5636,7 @@ function validateShellOpenPayload(payload) {
|
|
|
5559
5636
|
return {
|
|
5560
5637
|
ok: true,
|
|
5561
5638
|
value: {
|
|
5562
|
-
path:
|
|
5639
|
+
path: path24,
|
|
5563
5640
|
...target !== void 0 ? { target } : {}
|
|
5564
5641
|
}
|
|
5565
5642
|
};
|
|
@@ -5568,14 +5645,14 @@ function validateGitDiffPayload(payload) {
|
|
|
5568
5645
|
if (!isRecord(payload)) {
|
|
5569
5646
|
return { ok: false, message: "git.diff payload must be an object" };
|
|
5570
5647
|
}
|
|
5571
|
-
const
|
|
5572
|
-
if (
|
|
5648
|
+
const path24 = payload["path"];
|
|
5649
|
+
if (path24 === void 0 || path24 === null) {
|
|
5573
5650
|
return { ok: true, value: { path: "" } };
|
|
5574
5651
|
}
|
|
5575
|
-
if (typeof
|
|
5652
|
+
if (typeof path24 !== "string") {
|
|
5576
5653
|
return { ok: false, message: "git.diff payload.path must be a string when provided" };
|
|
5577
5654
|
}
|
|
5578
|
-
return { ok: true, value: { path:
|
|
5655
|
+
return { ok: true, value: { path: path24 } };
|
|
5579
5656
|
}
|
|
5580
5657
|
|
|
5581
5658
|
// src/server/zip.ts
|
|
@@ -6544,7 +6621,7 @@ function registerShutdownHandlers(res) {
|
|
|
6544
6621
|
import { watch as fsWatch } from "node:fs";
|
|
6545
6622
|
import * as fs11 from "node:fs/promises";
|
|
6546
6623
|
import * as path13 from "node:path";
|
|
6547
|
-
import { getBoard, getKanbanDir } from "@wrongstack/kanban";
|
|
6624
|
+
import { getBoard, getKanbanDir, recordTaskFileActivity } from "@wrongstack/kanban";
|
|
6548
6625
|
|
|
6549
6626
|
// src/server/codemap-telemetry.ts
|
|
6550
6627
|
import * as path12 from "node:path";
|
|
@@ -6940,6 +7017,18 @@ function setupEvents(deps2) {
|
|
|
6940
7017
|
on("file.activity", (e) => {
|
|
6941
7018
|
broadcast2(clients, { type: "codemap.file_event", payload: e });
|
|
6942
7019
|
});
|
|
7020
|
+
on("file.event", (e) => {
|
|
7021
|
+
if (e.scope !== "task" || !e.boardId || !e.taskId) return;
|
|
7022
|
+
void recordTaskFileActivity(context.projectRoot, e.boardId, e.taskId, e).then((recorded) => {
|
|
7023
|
+
if (recorded) {
|
|
7024
|
+
broadcast2(clients, {
|
|
7025
|
+
type: "kanban.task.activity.changed",
|
|
7026
|
+
payload: { boardId: e.boardId, taskId: e.taskId }
|
|
7027
|
+
});
|
|
7028
|
+
}
|
|
7029
|
+
}).catch(() => {
|
|
7030
|
+
});
|
|
7031
|
+
});
|
|
6943
7032
|
on("tool.loop_detected", (e) => {
|
|
6944
7033
|
broadcast2(clients, {
|
|
6945
7034
|
type: "tool.loop_detected",
|
|
@@ -7064,12 +7153,14 @@ function setupEvents(deps2) {
|
|
|
7064
7153
|
input: e.input,
|
|
7065
7154
|
suggestedPattern: e.suggestedPattern,
|
|
7066
7155
|
decisionSource: e.decisionSource,
|
|
7067
|
-
riskTier: e.riskTier
|
|
7156
|
+
riskTier: e.riskTier,
|
|
7157
|
+
boundaryReason: e.boundaryReason
|
|
7068
7158
|
});
|
|
7069
7159
|
pendingConfirms.set(id, {
|
|
7070
7160
|
resolve: e.resolve,
|
|
7071
7161
|
decisionSource: e.decisionSource,
|
|
7072
7162
|
riskTier: e.riskTier,
|
|
7163
|
+
boundaryReason: e.boundaryReason,
|
|
7073
7164
|
payload
|
|
7074
7165
|
});
|
|
7075
7166
|
broadcast2(clients, { type: "tool.confirm_needed", payload });
|
|
@@ -7162,7 +7253,8 @@ function setupEvents(deps2) {
|
|
|
7162
7253
|
oldState: e.oldState,
|
|
7163
7254
|
newState: e.newState,
|
|
7164
7255
|
reason: e.reason,
|
|
7165
|
-
timestamp: e.timestamp
|
|
7256
|
+
timestamp: e.timestamp,
|
|
7257
|
+
stateExpiresAt: e.stateExpiresAt
|
|
7166
7258
|
})
|
|
7167
7259
|
});
|
|
7168
7260
|
});
|
|
@@ -8269,6 +8361,7 @@ function seedContextMeta(config, context) {
|
|
|
8269
8361
|
meta["fallbackProfiles"] = config.fallbackProfiles ?? {};
|
|
8270
8362
|
meta["favoriteModels"] = config.favoriteModels ?? [];
|
|
8271
8363
|
meta["favoriteModelsOnly"] = config.favoriteModelsOnly === true;
|
|
8364
|
+
meta["modelAvailabilitySchedule"] = config.modelAvailabilitySchedule ?? [];
|
|
8272
8365
|
meta["modelMatrix"] = config.modelMatrix ?? {};
|
|
8273
8366
|
meta["fallbackAuto"] = config.fallbackAuto !== false;
|
|
8274
8367
|
if (typeof config.uiLocale === "string" && config.uiLocale) meta["uiLocale"] = config.uiLocale;
|
|
@@ -8351,9 +8444,7 @@ function seedContextMeta(config, context) {
|
|
|
8351
8444
|
} catch {
|
|
8352
8445
|
resolvedChain = [];
|
|
8353
8446
|
}
|
|
8354
|
-
meta["autoReviewFallbackModels"] = resolvedChain.map(
|
|
8355
|
-
(e) => `${e.providerId}/${e.model}`
|
|
8356
|
-
);
|
|
8447
|
+
meta["autoReviewFallbackModels"] = resolvedChain.map((e) => `${e.providerId}/${e.model}`);
|
|
8357
8448
|
}
|
|
8358
8449
|
}
|
|
8359
8450
|
|
|
@@ -8891,7 +8982,7 @@ function isSuperMemoryService(memoryStore) {
|
|
|
8891
8982
|
}
|
|
8892
8983
|
|
|
8893
8984
|
// src/server/start-webui.ts
|
|
8894
|
-
import * as
|
|
8985
|
+
import * as path23 from "node:path";
|
|
8895
8986
|
import {
|
|
8896
8987
|
createDefaultPipelines,
|
|
8897
8988
|
createSessionEventBridge,
|
|
@@ -9810,7 +9901,7 @@ function setupWebUICodebaseIndexing(deps2) {
|
|
|
9810
9901
|
}
|
|
9811
9902
|
if (idx) {
|
|
9812
9903
|
cancelPendingReindexes();
|
|
9813
|
-
shutdownCodebaseIndexHost();
|
|
9904
|
+
void shutdownCodebaseIndexHost();
|
|
9814
9905
|
}
|
|
9815
9906
|
}
|
|
9816
9907
|
};
|
|
@@ -9977,6 +10068,9 @@ var DEFAULT_COLS = 80;
|
|
|
9977
10068
|
var DEFAULT_ROWS = 24;
|
|
9978
10069
|
var requireFromHere = createRequire4(import.meta.url);
|
|
9979
10070
|
var cachedNodePty;
|
|
10071
|
+
function resolveTerminalShell(platform = process.platform, env = process.env) {
|
|
10072
|
+
return platform === "win32" ? env.COMSPEC || "cmd.exe" : env.SHELL || "/bin/sh";
|
|
10073
|
+
}
|
|
9980
10074
|
var TerminalWebSocketHandler = class {
|
|
9981
10075
|
constructor(getCwd, logger, loadNodePty = defaultLoadNodePty, killProcessTree = defaultKillProcessTree) {
|
|
9982
10076
|
this.getCwd = getCwd;
|
|
@@ -10032,7 +10126,7 @@ var TerminalWebSocketHandler = class {
|
|
|
10032
10126
|
});
|
|
10033
10127
|
return;
|
|
10034
10128
|
}
|
|
10035
|
-
const shell =
|
|
10129
|
+
const shell = resolveTerminalShell();
|
|
10036
10130
|
const nodePty = this.loadNodePty();
|
|
10037
10131
|
if (!nodePty) {
|
|
10038
10132
|
const msg = "Integrated terminal unavailable: optional dependency node-pty is not installed. Install node-pty to enable WebUI terminal sessions.";
|
|
@@ -10352,7 +10446,11 @@ async function createAgentServices(input) {
|
|
|
10352
10446
|
toolExecutor
|
|
10353
10447
|
});
|
|
10354
10448
|
if (config.features.memory && config.features.memoryConsolidation !== false) {
|
|
10355
|
-
|
|
10449
|
+
const consSuperMemory = typeof memoryStore["rememberSuper"] === "function" ? memoryStore : void 0;
|
|
10450
|
+
agent.extensions.register(new SessionMemoryConsolidator({
|
|
10451
|
+
memoryStore,
|
|
10452
|
+
...consSuperMemory ? { superMemory: consSuperMemory } : {}
|
|
10453
|
+
}));
|
|
10356
10454
|
}
|
|
10357
10455
|
console.log("[WebUI] Agent initialized");
|
|
10358
10456
|
const brainCfg = resolveBrainConfigDefaults(config.brain, {
|
|
@@ -10558,6 +10656,7 @@ function isSuperMemoryRetriever(memoryStore) {
|
|
|
10558
10656
|
// src/server/pending-confirms.ts
|
|
10559
10657
|
function resolveYoloEligiblePendingConfirms(pendingConfirms) {
|
|
10560
10658
|
for (const [id, confirm] of pendingConfirms) {
|
|
10659
|
+
if (confirm.boundaryReason) continue;
|
|
10561
10660
|
pendingConfirms.delete(id);
|
|
10562
10661
|
confirm.resolve("yes");
|
|
10563
10662
|
}
|
|
@@ -11037,7 +11136,7 @@ import {
|
|
|
11037
11136
|
createBoard,
|
|
11038
11137
|
duplicateBoard,
|
|
11039
11138
|
exportBoardToTaskGraph,
|
|
11040
|
-
|
|
11139
|
+
createBoardFromText,
|
|
11041
11140
|
getBoard as getBoard2,
|
|
11042
11141
|
getKanbanOrchestrationSnapshot,
|
|
11043
11142
|
getKanbanQueueHealth,
|
|
@@ -11068,6 +11167,32 @@ import {
|
|
|
11068
11167
|
updateTask
|
|
11069
11168
|
} from "@wrongstack/kanban";
|
|
11070
11169
|
import { applySessionKanbanTaskToSource } from "@wrongstack/tools/session-kanban";
|
|
11170
|
+
function paginateKanbanBoards(boards, input) {
|
|
11171
|
+
const pageSize = Math.min(100, Math.max(1, Math.floor(input.pageSize)));
|
|
11172
|
+
const activeSessionIds = new Set(input.activeSessionIds ?? []);
|
|
11173
|
+
const isActive = (board) => board.presence?.some((entry) => entry.active) === true || board.tags?.some(
|
|
11174
|
+
(tag) => tag.startsWith("session:") && activeSessionIds.has(tag.slice(8))
|
|
11175
|
+
) === true;
|
|
11176
|
+
const sorted = [...boards].sort((left, right) => {
|
|
11177
|
+
const activityOrder = Number(isActive(right)) - Number(isActive(left));
|
|
11178
|
+
return activityOrder || right.updatedAt.localeCompare(left.updatedAt);
|
|
11179
|
+
});
|
|
11180
|
+
const activeTotal = sorted.filter(isActive).length;
|
|
11181
|
+
const total = sorted.length;
|
|
11182
|
+
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
11183
|
+
const requestedPage = Number.isFinite(input.page) ? Math.floor(input.page) : 1;
|
|
11184
|
+
const page = Math.min(totalPages, Math.max(1, requestedPage));
|
|
11185
|
+
const start = (page - 1) * pageSize;
|
|
11186
|
+
return {
|
|
11187
|
+
items: sorted.slice(start, start + pageSize),
|
|
11188
|
+
total,
|
|
11189
|
+
page,
|
|
11190
|
+
pageSize,
|
|
11191
|
+
totalPages,
|
|
11192
|
+
activeTotal,
|
|
11193
|
+
orphanedTotal: total - activeTotal
|
|
11194
|
+
};
|
|
11195
|
+
}
|
|
11071
11196
|
async function syncSessionSource(ctx, task, remove = false) {
|
|
11072
11197
|
if (!ctx.context) return;
|
|
11073
11198
|
const update = await applySessionKanbanTaskToSource(ctx.context, task, { remove });
|
|
@@ -11117,9 +11242,26 @@ async function handleKanbanRoute(ws, msg, ctx) {
|
|
|
11117
11242
|
const type = msg.type;
|
|
11118
11243
|
try {
|
|
11119
11244
|
switch (type) {
|
|
11120
|
-
case "kanban.list":
|
|
11121
|
-
|
|
11245
|
+
case "kanban.list": {
|
|
11246
|
+
const boards = await listBoards(ctx.projectRoot);
|
|
11247
|
+
const requestedPage = Number(payload?.page);
|
|
11248
|
+
const requestedPageSize = Number(payload?.pageSize);
|
|
11249
|
+
if (!Number.isFinite(requestedPage) || !Number.isFinite(requestedPageSize)) {
|
|
11250
|
+
ok(ws, type, boards);
|
|
11251
|
+
return true;
|
|
11252
|
+
}
|
|
11253
|
+
const activeSessionIds = Array.isArray(payload?.activeSessionIds) ? payload.activeSessionIds.filter((id) => typeof id === "string") : [];
|
|
11254
|
+
ok(
|
|
11255
|
+
ws,
|
|
11256
|
+
type,
|
|
11257
|
+
paginateKanbanBoards(boards, {
|
|
11258
|
+
page: requestedPage,
|
|
11259
|
+
pageSize: requestedPageSize,
|
|
11260
|
+
activeSessionIds
|
|
11261
|
+
})
|
|
11262
|
+
);
|
|
11122
11263
|
return true;
|
|
11264
|
+
}
|
|
11123
11265
|
case "kanban.get": {
|
|
11124
11266
|
const boardId = payload?.boardId;
|
|
11125
11267
|
if (!boardId) {
|
|
@@ -11185,7 +11327,8 @@ async function handleKanbanRoute(ws, msg, ctx) {
|
|
|
11185
11327
|
...payload?.description ? { description: payload.description } : {},
|
|
11186
11328
|
...payload?.tags ? { tags: payload.tags } : {},
|
|
11187
11329
|
...payload?.columns ? { columns: payload.columns } : {},
|
|
11188
|
-
...has(payload, "lifecycle") ? { lifecycle: payload?.lifecycle } : {}
|
|
11330
|
+
...has(payload, "lifecycle") ? { lifecycle: payload?.lifecycle } : {},
|
|
11331
|
+
...has(payload, "boundary") ? { boundary: payload?.boundary } : {}
|
|
11189
11332
|
})
|
|
11190
11333
|
);
|
|
11191
11334
|
return true;
|
|
@@ -11206,6 +11349,9 @@ async function handleKanbanRoute(ws, msg, ctx) {
|
|
|
11206
11349
|
} : {},
|
|
11207
11350
|
...has(payload, "supervisor") ? {
|
|
11208
11351
|
supervisor: payload?.supervisor ?? null
|
|
11352
|
+
} : {},
|
|
11353
|
+
...has(payload, "boundary") ? {
|
|
11354
|
+
boundary: payload?.boundary ?? null
|
|
11209
11355
|
} : {}
|
|
11210
11356
|
});
|
|
11211
11357
|
board ? ok(ws, type, board) : fail(ws, type, `Board not found: ${boardId}`);
|
|
@@ -11252,7 +11398,7 @@ async function handleKanbanRoute(ws, msg, ctx) {
|
|
|
11252
11398
|
}
|
|
11253
11399
|
const board = await createBoard(
|
|
11254
11400
|
ctx.projectRoot,
|
|
11255
|
-
|
|
11401
|
+
createBoardFromText({
|
|
11256
11402
|
description,
|
|
11257
11403
|
...payload?.title ? { title: payload.title } : {},
|
|
11258
11404
|
...payload?.context ? { context: payload.context } : {}
|
|
@@ -11364,7 +11510,8 @@ async function handleKanbanRoute(ws, msg, ctx) {
|
|
|
11364
11510
|
...payload?.dueDate ? { dueDate: payload.dueDate } : {},
|
|
11365
11511
|
...payload?.priority ? { priority: payload.priority } : {},
|
|
11366
11512
|
...payload?.assignedAgent ? { assignedAgent: payload.assignedAgent } : {},
|
|
11367
|
-
...payload?.labels ? { labels: payload.labels } : {}
|
|
11513
|
+
...payload?.labels ? { labels: payload.labels } : {},
|
|
11514
|
+
...has(payload, "boundary") ? { boundary: payload?.boundary } : {}
|
|
11368
11515
|
},
|
|
11369
11516
|
activityContext(ctx, "webui", payload?.activityNote)
|
|
11370
11517
|
);
|
|
@@ -11445,6 +11592,9 @@ async function handleKanbanRoute(ws, msg, ctx) {
|
|
|
11445
11592
|
} : {},
|
|
11446
11593
|
...has(payload, "costCeilingUsd") ? {
|
|
11447
11594
|
costCeilingUsd: payload?.costCeilingUsd === null || payload?.costCeilingUsd === "" ? null : Number(payload?.costCeilingUsd)
|
|
11595
|
+
} : {},
|
|
11596
|
+
...has(payload, "boundary") ? {
|
|
11597
|
+
boundary: payload?.boundary ?? null
|
|
11448
11598
|
} : {}
|
|
11449
11599
|
},
|
|
11450
11600
|
activityContext(ctx, "webui", payload?.activityNote)
|
|
@@ -12337,7 +12487,7 @@ var chronicleCache = /* @__PURE__ */ new Map();
|
|
|
12337
12487
|
async function chronicleEngine(projectRoot) {
|
|
12338
12488
|
const now = Date.now();
|
|
12339
12489
|
const cached = chronicleCache.get(projectRoot);
|
|
12340
|
-
if (cached && now - cached.loadedAt <
|
|
12490
|
+
if (cached && now - cached.loadedAt < 6e4) return cached.engine;
|
|
12341
12491
|
const paths = resolveWstackPaths2({ projectRoot, userHome: os2.homedir() });
|
|
12342
12492
|
const engine = await ChronicleQueryEngine.fromDirectory(
|
|
12343
12493
|
path19.join(paths.projectDir, "chronicle")
|
|
@@ -12600,6 +12750,8 @@ function createMessageDispatcher(opts) {
|
|
|
12600
12750
|
// ── SuperMemory operations ──
|
|
12601
12751
|
case "memory.super.list":
|
|
12602
12752
|
return handleSuperMemoryList(ws, deps2.memoryStore);
|
|
12753
|
+
case "memory.super.listPage":
|
|
12754
|
+
return handleSuperMemoryListPage(ws, msg, deps2.memoryStore);
|
|
12603
12755
|
case "memory.super.get":
|
|
12604
12756
|
return handleSuperMemoryGet(ws, msg, deps2.memoryStore);
|
|
12605
12757
|
case "memory.super.update":
|
|
@@ -12854,7 +13006,7 @@ function createMessageDispatcher(opts) {
|
|
|
12854
13006
|
case "chronicle.query": {
|
|
12855
13007
|
const payload = msg.payload ?? {};
|
|
12856
13008
|
const engine = await chronicleEngine(state.getProjectRoot());
|
|
12857
|
-
send(ws, { type: "chronicle.query_result", payload: engine.query(payload.query ?? {}) });
|
|
13009
|
+
send(ws, { type: "chronicle.query_result", payload: await engine.query(payload.query ?? {}) });
|
|
12858
13010
|
break;
|
|
12859
13011
|
}
|
|
12860
13012
|
case "chronicle.facet": {
|
|
@@ -12884,7 +13036,7 @@ function createMessageDispatcher(opts) {
|
|
|
12884
13036
|
type: "chronicle.facet_result",
|
|
12885
13037
|
payload: {
|
|
12886
13038
|
field: payload.field,
|
|
12887
|
-
values: engine.facet(payload.field, payload.query ?? {}, payload.limit),
|
|
13039
|
+
values: await engine.facet(payload.field, payload.query ?? {}, payload.limit),
|
|
12888
13040
|
diagnostics: engine.diagnostics
|
|
12889
13041
|
}
|
|
12890
13042
|
});
|
|
@@ -12895,7 +13047,7 @@ function createMessageDispatcher(opts) {
|
|
|
12895
13047
|
const engine = await chronicleEngine(state.getProjectRoot());
|
|
12896
13048
|
send(ws, {
|
|
12897
13049
|
type: "chronicle.graph_result",
|
|
12898
|
-
payload: engine.graph(payload.seed ?? {}, payload.hops, payload.maxNodes)
|
|
13050
|
+
payload: await engine.graph(payload.seed ?? {}, payload.hops, payload.maxNodes)
|
|
12899
13051
|
});
|
|
12900
13052
|
break;
|
|
12901
13053
|
}
|
|
@@ -12950,9 +13102,10 @@ function createMessageDispatcher(opts) {
|
|
|
12950
13102
|
}
|
|
12951
13103
|
|
|
12952
13104
|
// src/server/pref-helpers.ts
|
|
12953
|
-
import { atomicWrite as atomicWrite6, FORBIDDEN_PROTO_KEYS as FORBIDDEN_PROTO_KEYS2 } from "@wrongstack/core/utils";
|
|
12954
|
-
import { decryptConfigSecrets as decryptConfigSecrets2, encryptConfigSecrets as encryptConfigSecrets2 } from "@wrongstack/core/security";
|
|
12955
13105
|
import * as fs14 from "node:fs/promises";
|
|
13106
|
+
import * as path20 from "node:path";
|
|
13107
|
+
import { decryptConfigSecrets as decryptConfigSecrets2, encryptConfigSecrets as encryptConfigSecrets2 } from "@wrongstack/core/security";
|
|
13108
|
+
import { atomicWrite as atomicWrite6, backupConfigFile, FORBIDDEN_PROTO_KEYS as FORBIDDEN_PROTO_KEYS2 } from "@wrongstack/core/utils";
|
|
12956
13109
|
var PREF_KEYS = [
|
|
12957
13110
|
"autonomy",
|
|
12958
13111
|
"autonomyDelayMs",
|
|
@@ -12997,6 +13150,7 @@ var PREF_KEYS = [
|
|
|
12997
13150
|
"fallbackProfiles",
|
|
12998
13151
|
"favoriteModels",
|
|
12999
13152
|
"favoriteModelsOnly",
|
|
13153
|
+
"modelAvailabilitySchedule",
|
|
13000
13154
|
"modelMatrix",
|
|
13001
13155
|
"fallbackAuto",
|
|
13002
13156
|
// Refiner + TUI visual prefs (parity with the CLI's embedded server —
|
|
@@ -13040,26 +13194,34 @@ function prefSnapshot(contextMeta) {
|
|
|
13040
13194
|
}
|
|
13041
13195
|
return snapshot;
|
|
13042
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
|
+
}
|
|
13043
13218
|
async function updateGlobalConfig(deps2, holder, mutate, errorLabel) {
|
|
13044
|
-
const { globalConfigPath, vault, logger } = deps2;
|
|
13219
|
+
const { globalConfigPath, profileConfigPath, vault, logger } = deps2;
|
|
13045
13220
|
const write = async () => {
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
} catch {
|
|
13050
|
-
raw = "{}";
|
|
13221
|
+
await writeGlobalConfigFile(globalConfigPath, vault, mutate, logger, errorLabel);
|
|
13222
|
+
if (profileConfigPath && profileConfigPath !== globalConfigPath) {
|
|
13223
|
+
await writeGlobalConfigFile(profileConfigPath, vault, mutate, logger, errorLabel);
|
|
13051
13224
|
}
|
|
13052
|
-
let parsed;
|
|
13053
|
-
try {
|
|
13054
|
-
parsed = JSON.parse(raw);
|
|
13055
|
-
} catch {
|
|
13056
|
-
logger.warn(`${errorLabel}: refusing to overwrite corrupt config at ${globalConfigPath}`);
|
|
13057
|
-
return;
|
|
13058
|
-
}
|
|
13059
|
-
const decrypted = decryptConfigSecrets2(parsed, vault);
|
|
13060
|
-
mutate(decrypted);
|
|
13061
|
-
const encrypted = encryptConfigSecrets2(decrypted, vault);
|
|
13062
|
-
await atomicWrite6(globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
13063
13225
|
};
|
|
13064
13226
|
const next = holder.lock.then(write);
|
|
13065
13227
|
holder.lock = next.then(
|
|
@@ -13069,256 +13231,264 @@ async function updateGlobalConfig(deps2, holder, mutate, errorLabel) {
|
|
|
13069
13231
|
try {
|
|
13070
13232
|
await next;
|
|
13071
13233
|
} catch (err) {
|
|
13072
|
-
logger.warn(
|
|
13234
|
+
logger.warn(
|
|
13235
|
+
`${errorLabel}: failed to persist to config: ${err instanceof Error ? err.message : String(err)}`
|
|
13236
|
+
);
|
|
13073
13237
|
}
|
|
13074
13238
|
}
|
|
13075
13239
|
async function persistPrefsToConfig(deps2, holder, payload) {
|
|
13076
|
-
return updateGlobalConfig(
|
|
13077
|
-
|
|
13078
|
-
|
|
13079
|
-
|
|
13080
|
-
autonomyCfg
|
|
13081
|
-
autonomyTouched =
|
|
13082
|
-
|
|
13083
|
-
|
|
13084
|
-
|
|
13085
|
-
|
|
13086
|
-
|
|
13087
|
-
|
|
13088
|
-
if (typeof payload["autoProceedMaxIterations"] === "number")
|
|
13089
|
-
setAutonomy("autoProceedMaxIterations", payload["autoProceedMaxIterations"]);
|
|
13090
|
-
if (typeof payload["yolo"] === "boolean") {
|
|
13091
|
-
setAutonomy("yolo", payload["yolo"]);
|
|
13092
|
-
decrypted.yolo = payload["yolo"];
|
|
13093
|
-
}
|
|
13094
|
-
if (typeof payload["chime"] === "boolean") setAutonomy("chime", payload["chime"]);
|
|
13095
|
-
if (typeof payload["confirmExit"] === "boolean")
|
|
13096
|
-
setAutonomy("confirmExit", payload["confirmExit"]);
|
|
13097
|
-
if (typeof payload["streamFleet"] === "boolean")
|
|
13098
|
-
setAutonomy("streamFleet", payload["streamFleet"]);
|
|
13099
|
-
if (typeof payload["enhanceEnabled"] === "boolean")
|
|
13100
|
-
setAutonomy("enhance", payload["enhanceEnabled"]);
|
|
13101
|
-
if (typeof payload["enhanceDelayMs"] === "number")
|
|
13102
|
-
setAutonomy("enhanceDelayMs", payload["enhanceDelayMs"]);
|
|
13103
|
-
if (typeof payload["enhanceLanguage"] === "string")
|
|
13104
|
-
setAutonomy("enhanceLanguage", payload["enhanceLanguage"]);
|
|
13105
|
-
if (typeof payload["refinerProvider"] === "string")
|
|
13106
|
-
setAutonomy("refinerProvider", payload["refinerProvider"]);
|
|
13107
|
-
if (typeof payload["refinerModel"] === "string")
|
|
13108
|
-
setAutonomy("refinerModel", payload["refinerModel"]);
|
|
13109
|
-
if (typeof payload["refinerFallbackProfile"] === "string")
|
|
13110
|
-
setAutonomy("refinerFallbackProfile", payload["refinerFallbackProfile"]);
|
|
13111
|
-
if (typeof payload["thinkingWord"] === "string")
|
|
13112
|
-
setAutonomy("thinkingWord", payload["thinkingWord"]);
|
|
13113
|
-
if (typeof payload["statuslineMode"] === "string")
|
|
13114
|
-
setAutonomy("statuslineMode", payload["statuslineMode"]);
|
|
13115
|
-
if (typeof payload["animationStyle"] === "string")
|
|
13116
|
-
setAutonomy("animationStyle", payload["animationStyle"]);
|
|
13117
|
-
if (typeof payload["showModelReasoning"] === "boolean")
|
|
13118
|
-
setAutonomy("showModelReasoning", payload["showModelReasoning"]);
|
|
13119
|
-
if (autonomyTouched) decrypted.autonomy = autonomyCfg;
|
|
13120
|
-
if (typeof payload["nextPrediction"] === "boolean")
|
|
13121
|
-
decrypted.nextPrediction = payload["nextPrediction"];
|
|
13122
|
-
if (typeof payload["uiLocale"] === "string") decrypted.uiLocale = payload["uiLocale"];
|
|
13123
|
-
if (Array.isArray(payload["fallbackModels"]))
|
|
13124
|
-
decrypted.fallbackModels = payload["fallbackModels"];
|
|
13125
|
-
if (payload["fallbackProfiles"] && typeof payload["fallbackProfiles"] === "object" && !Array.isArray(payload["fallbackProfiles"])) {
|
|
13126
|
-
decrypted.fallbackProfiles = payload["fallbackProfiles"];
|
|
13127
|
-
}
|
|
13128
|
-
if (Array.isArray(payload["favoriteModels"]))
|
|
13129
|
-
decrypted.favoriteModels = payload["favoriteModels"];
|
|
13130
|
-
if (typeof payload["favoriteModelsOnly"] === "boolean")
|
|
13131
|
-
decrypted.favoriteModelsOnly = payload["favoriteModelsOnly"];
|
|
13132
|
-
if (payload["modelMatrix"] && typeof payload["modelMatrix"] === "object" && !Array.isArray(payload["modelMatrix"])) {
|
|
13133
|
-
decrypted.modelMatrix = payload["modelMatrix"];
|
|
13134
|
-
}
|
|
13135
|
-
if (typeof payload["fallbackAuto"] === "boolean")
|
|
13136
|
-
decrypted.fallbackAuto = payload["fallbackAuto"];
|
|
13137
|
-
const FEATURE_MAP = {
|
|
13138
|
-
featureMcp: "mcp",
|
|
13139
|
-
featurePlugins: "plugins",
|
|
13140
|
-
featureMemory: "memory",
|
|
13141
|
-
featureSkills: "skills",
|
|
13142
|
-
featureModelsRegistry: "modelsRegistry"
|
|
13143
|
-
};
|
|
13144
|
-
for (const [prefKey, cfgKey] of Object.entries(FEATURE_MAP)) {
|
|
13145
|
-
if (typeof payload[prefKey] === "boolean") {
|
|
13146
|
-
const feats = decrypted.features ?? {};
|
|
13147
|
-
feats[cfgKey] = payload[prefKey];
|
|
13148
|
-
decrypted.features = feats;
|
|
13149
|
-
}
|
|
13150
|
-
}
|
|
13151
|
-
if (typeof payload["contextAutoCompact"] === "boolean" || typeof payload["contextStrategy"] === "string" || typeof payload["contextMode"] === "string") {
|
|
13152
|
-
const ctxCfg = decrypted.context ?? {};
|
|
13153
|
-
if (typeof payload["contextAutoCompact"] === "boolean")
|
|
13154
|
-
ctxCfg.autoCompact = payload["contextAutoCompact"];
|
|
13155
|
-
if (typeof payload["contextStrategy"] === "string")
|
|
13156
|
-
ctxCfg.strategy = payload["contextStrategy"];
|
|
13157
|
-
if (typeof payload["contextMode"] === "string") ctxCfg.mode = payload["contextMode"];
|
|
13158
|
-
decrypted.context = ctxCfg;
|
|
13159
|
-
}
|
|
13160
|
-
if (typeof payload["tokenSavingTier"] === "string") {
|
|
13161
|
-
const featsCfg = decrypted.features ?? {};
|
|
13162
|
-
featsCfg.tokenSavingMode = payload["tokenSavingTier"];
|
|
13163
|
-
decrypted.features = featsCfg;
|
|
13164
|
-
}
|
|
13165
|
-
if (typeof payload["maxConcurrent"] === "number") {
|
|
13166
|
-
decrypted.maxConcurrent = payload["maxConcurrent"];
|
|
13167
|
-
}
|
|
13168
|
-
if (typeof payload["titleAnimation"] === "boolean") {
|
|
13169
|
-
const autoCfg = decrypted.autonomy ?? {};
|
|
13170
|
-
autoCfg.terminalTitleAnimation = payload["titleAnimation"];
|
|
13171
|
-
decrypted.autonomy = autoCfg;
|
|
13172
|
-
}
|
|
13173
|
-
if (typeof payload["logLevel"] === "string") {
|
|
13174
|
-
const logCfg = decrypted.log ?? {};
|
|
13175
|
-
logCfg.level = payload["logLevel"];
|
|
13176
|
-
decrypted.log = logCfg;
|
|
13177
|
-
}
|
|
13178
|
-
if (typeof payload["auditLevel"] === "string") {
|
|
13179
|
-
const sessionCfg = decrypted.session ?? {};
|
|
13180
|
-
sessionCfg.auditLevel = payload["auditLevel"];
|
|
13181
|
-
decrypted.session = sessionCfg;
|
|
13182
|
-
}
|
|
13183
|
-
if (typeof payload["indexOnStart"] === "boolean") {
|
|
13184
|
-
const indexingCfg = decrypted.indexing ?? {};
|
|
13185
|
-
indexingCfg.onSessionStart = payload["indexOnStart"];
|
|
13186
|
-
decrypted.indexing = indexingCfg;
|
|
13187
|
-
}
|
|
13188
|
-
if (typeof payload["maxIterations"] === "number") {
|
|
13189
|
-
const toolsCfg = decrypted.tools ?? {};
|
|
13190
|
-
toolsCfg.maxIterations = payload["maxIterations"];
|
|
13191
|
-
decrypted.tools = toolsCfg;
|
|
13192
|
-
}
|
|
13193
|
-
const hqTouched = typeof payload["hqEnabled"] === "boolean" || typeof payload["hqUrl"] === "string" || typeof payload["hqToken"] === "string" || typeof payload["hqRawContent"] === "boolean";
|
|
13194
|
-
if (hqTouched) {
|
|
13195
|
-
const hqCfg = decrypted.hq ?? {};
|
|
13196
|
-
if (typeof payload["hqEnabled"] === "boolean") hqCfg.enabled = payload["hqEnabled"];
|
|
13197
|
-
if (typeof payload["hqUrl"] === "string") hqCfg.url = payload["hqUrl"];
|
|
13198
|
-
if (typeof payload["hqToken"] === "string") hqCfg.token = payload["hqToken"];
|
|
13199
|
-
if (typeof payload["hqRawContent"] === "boolean")
|
|
13200
|
-
hqCfg.rawContent = payload["hqRawContent"];
|
|
13201
|
-
decrypted.hq = hqCfg;
|
|
13202
|
-
}
|
|
13203
|
-
const tgTouched = typeof payload["tgSessionEnd"] === "boolean" || typeof payload["tgDelegate"] === "boolean" || typeof payload["tgLongToolMs"] === "number";
|
|
13204
|
-
if (tgTouched) {
|
|
13205
|
-
const ext = decrypted.extensions ?? {};
|
|
13206
|
-
const tg = ext["telegram"] ?? {};
|
|
13207
|
-
if (typeof payload["tgSessionEnd"] === "boolean") {
|
|
13208
|
-
tg["notifyOnSessionEnd"] = payload["tgSessionEnd"];
|
|
13209
|
-
}
|
|
13210
|
-
if (typeof payload["tgDelegate"] === "boolean") {
|
|
13211
|
-
tg["notifyOnDelegate"] = payload["tgDelegate"];
|
|
13212
|
-
}
|
|
13213
|
-
if (typeof payload["tgLongToolMs"] === "number") {
|
|
13214
|
-
tg["longToolThresholdMs"] = payload["tgLongToolMs"];
|
|
13215
|
-
}
|
|
13216
|
-
ext["telegram"] = tg;
|
|
13217
|
-
decrypted.extensions = ext;
|
|
13218
|
-
}
|
|
13219
|
-
const modelRuntimeTouched = typeof payload["reasoningMode"] === "string" || typeof payload["reasoningEffort"] === "string" || typeof payload["reasoningPreserve"] === "boolean" || typeof payload["cacheTtl"] === "string";
|
|
13220
|
-
if (modelRuntimeTouched) {
|
|
13221
|
-
const mr = decrypted.modelRuntime ?? {};
|
|
13222
|
-
const reasoning = mr.reasoning ?? {};
|
|
13223
|
-
if (typeof payload["reasoningMode"] === "string") reasoning.mode = payload["reasoningMode"];
|
|
13224
|
-
if (typeof payload["reasoningEffort"] === "string")
|
|
13225
|
-
reasoning.effort = payload["reasoningEffort"];
|
|
13226
|
-
if (typeof payload["reasoningPreserve"] === "boolean")
|
|
13227
|
-
reasoning.preserve = payload["reasoningPreserve"];
|
|
13228
|
-
mr.reasoning = reasoning;
|
|
13229
|
-
if (typeof payload["cacheTtl"] === "string" && payload["cacheTtl"] !== "default") {
|
|
13230
|
-
mr.cache = { ttl: payload["cacheTtl"] };
|
|
13231
|
-
} else if (payload["cacheTtl"] === "default") {
|
|
13232
|
-
delete mr.cache;
|
|
13233
|
-
}
|
|
13234
|
-
decrypted.modelRuntime = mr;
|
|
13235
|
-
}
|
|
13236
|
-
if (typeof payload["breakerEnabled"] === "boolean" || typeof payload["breakerAutoKillResetMs"] === "number") {
|
|
13237
|
-
const cb = decrypted.circuitBreaker ?? {};
|
|
13238
|
-
if (typeof payload["breakerEnabled"] === "boolean") cb.enabled = payload["breakerEnabled"];
|
|
13239
|
-
if (typeof payload["breakerAutoKillResetMs"] === "number")
|
|
13240
|
-
cb.autoKillResetMs = payload["breakerAutoKillResetMs"];
|
|
13241
|
-
decrypted.circuitBreaker = cb;
|
|
13242
|
-
}
|
|
13243
|
-
if (payload["fsAccess"] === "unrestricted" || payload["fsAccess"] === "project") {
|
|
13244
|
-
const restrict = payload["fsAccess"] === "project";
|
|
13245
|
-
const toolsCfg = decrypted.tools ?? {};
|
|
13246
|
-
toolsCfg.restrictToProjectRoot = restrict;
|
|
13247
|
-
decrypted.tools = toolsCfg;
|
|
13248
|
-
const featsCfg = decrypted.features ?? {};
|
|
13249
|
-
featsCfg.allowOutsideProjectRoot = !restrict;
|
|
13250
|
-
decrypted.features = featsCfg;
|
|
13251
|
-
}
|
|
13252
|
-
if (typeof payload["debugStream"] === "boolean")
|
|
13253
|
-
decrypted.debugStream = payload["debugStream"];
|
|
13254
|
-
if (typeof payload["pluginsEnabled"] === "object" && payload["pluginsEnabled"] !== null) {
|
|
13255
|
-
const ext = decrypted.extensions ?? {};
|
|
13256
|
-
for (const [pluginName, enabled] of Object.entries(
|
|
13257
|
-
payload["pluginsEnabled"]
|
|
13258
|
-
)) {
|
|
13259
|
-
if (FORBIDDEN_PROTO_KEYS2.has(pluginName)) continue;
|
|
13260
|
-
const pExt = ext[pluginName] ?? {};
|
|
13261
|
-
pExt["enabled"] = enabled;
|
|
13262
|
-
ext[pluginName] = pExt;
|
|
13263
|
-
}
|
|
13264
|
-
decrypted.extensions = ext;
|
|
13265
|
-
}
|
|
13266
|
-
const chimeraTouched = typeof payload["chimeraEnabled"] === "boolean" || typeof payload["chimeraProvider"] === "string" || typeof payload["chimeraModel"] === "string" || typeof payload["chimeraMaxFiles"] === "number" || typeof payload["chimeraAutoFix"] === "string";
|
|
13267
|
-
if (chimeraTouched) {
|
|
13268
|
-
const ext = decrypted.extensions ?? {};
|
|
13269
|
-
const chimera = ext["wstack-chimera"] ?? {};
|
|
13270
|
-
if (typeof payload["chimeraEnabled"] === "boolean")
|
|
13271
|
-
chimera["enabled"] = payload["chimeraEnabled"];
|
|
13272
|
-
if (typeof payload["chimeraProvider"] === "string")
|
|
13273
|
-
chimera["provider"] = payload["chimeraProvider"];
|
|
13274
|
-
if (typeof payload["chimeraModel"] === "string")
|
|
13275
|
-
chimera["model"] = payload["chimeraModel"];
|
|
13276
|
-
if (typeof payload["chimeraMaxFiles"] === "number" && payload["chimeraMaxFiles"] >= 1) {
|
|
13277
|
-
chimera["maxFiles"] = payload["chimeraMaxFiles"];
|
|
13278
|
-
}
|
|
13279
|
-
if (typeof payload["chimeraAutoFix"] === "string") {
|
|
13280
|
-
if (payload["chimeraAutoFix"] === "off" || payload["chimeraAutoFix"] === "ask" || payload["chimeraAutoFix"] === "auto") {
|
|
13281
|
-
chimera["autoFix"] = payload["chimeraAutoFix"];
|
|
13282
|
-
}
|
|
13283
|
-
}
|
|
13284
|
-
ext["wstack-chimera"] = chimera;
|
|
13285
|
-
decrypted.extensions = ext;
|
|
13286
|
-
}
|
|
13287
|
-
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";
|
|
13288
|
-
if (autoReviewTouched) {
|
|
13289
|
-
const ext = decrypted.extensions ?? {};
|
|
13290
|
-
const ar = ext["wstack-auto-review"] ?? {};
|
|
13291
|
-
if (typeof payload["autoReviewEnabled"] === "boolean")
|
|
13292
|
-
ar["enabled"] = payload["autoReviewEnabled"];
|
|
13293
|
-
if (typeof payload["autoReviewProvider"] === "string")
|
|
13294
|
-
ar["provider"] = payload["autoReviewProvider"];
|
|
13295
|
-
if (typeof payload["autoReviewModel"] === "string")
|
|
13296
|
-
ar["model"] = payload["autoReviewModel"];
|
|
13297
|
-
if (typeof payload["autoReviewFallbackProfile"] === "string") {
|
|
13298
|
-
if (payload["autoReviewFallbackProfile"] === "") {
|
|
13299
|
-
delete ar["fallbackProfile"];
|
|
13300
|
-
} else {
|
|
13301
|
-
ar["fallbackProfile"] = payload["autoReviewFallbackProfile"];
|
|
13302
|
-
}
|
|
13240
|
+
return updateGlobalConfig(
|
|
13241
|
+
deps2,
|
|
13242
|
+
holder,
|
|
13243
|
+
(decrypted) => {
|
|
13244
|
+
const autonomyCfg = decrypted.autonomy ?? {};
|
|
13245
|
+
let autonomyTouched = false;
|
|
13246
|
+
const setAutonomy = (key, val) => {
|
|
13247
|
+
autonomyCfg[key] = val;
|
|
13248
|
+
autonomyTouched = true;
|
|
13249
|
+
};
|
|
13250
|
+
if (typeof payload["autonomy"] === "string" && ["off", "suggest", "auto"].includes(payload["autonomy"])) {
|
|
13251
|
+
setAutonomy("defaultMode", payload["autonomy"]);
|
|
13303
13252
|
}
|
|
13304
|
-
if (typeof payload["
|
|
13305
|
-
|
|
13253
|
+
if (typeof payload["autonomyDelayMs"] === "number")
|
|
13254
|
+
setAutonomy("autoProceedDelayMs", payload["autonomyDelayMs"]);
|
|
13255
|
+
if (typeof payload["autoProceedMaxIterations"] === "number")
|
|
13256
|
+
setAutonomy("autoProceedMaxIterations", payload["autoProceedMaxIterations"]);
|
|
13257
|
+
if (typeof payload["yolo"] === "boolean") {
|
|
13258
|
+
setAutonomy("yolo", payload["yolo"]);
|
|
13259
|
+
decrypted.yolo = payload["yolo"];
|
|
13260
|
+
}
|
|
13261
|
+
if (typeof payload["chime"] === "boolean") setAutonomy("chime", payload["chime"]);
|
|
13262
|
+
if (typeof payload["confirmExit"] === "boolean")
|
|
13263
|
+
setAutonomy("confirmExit", payload["confirmExit"]);
|
|
13264
|
+
if (typeof payload["streamFleet"] === "boolean")
|
|
13265
|
+
setAutonomy("streamFleet", payload["streamFleet"]);
|
|
13266
|
+
if (typeof payload["enhanceEnabled"] === "boolean")
|
|
13267
|
+
setAutonomy("enhance", payload["enhanceEnabled"]);
|
|
13268
|
+
if (typeof payload["enhanceDelayMs"] === "number")
|
|
13269
|
+
setAutonomy("enhanceDelayMs", payload["enhanceDelayMs"]);
|
|
13270
|
+
if (typeof payload["enhanceLanguage"] === "string")
|
|
13271
|
+
setAutonomy("enhanceLanguage", payload["enhanceLanguage"]);
|
|
13272
|
+
if (typeof payload["refinerProvider"] === "string")
|
|
13273
|
+
setAutonomy("refinerProvider", payload["refinerProvider"]);
|
|
13274
|
+
if (typeof payload["refinerModel"] === "string")
|
|
13275
|
+
setAutonomy("refinerModel", payload["refinerModel"]);
|
|
13276
|
+
if (typeof payload["refinerFallbackProfile"] === "string")
|
|
13277
|
+
setAutonomy("refinerFallbackProfile", payload["refinerFallbackProfile"]);
|
|
13278
|
+
if (typeof payload["thinkingWord"] === "string")
|
|
13279
|
+
setAutonomy("thinkingWord", payload["thinkingWord"]);
|
|
13280
|
+
if (typeof payload["statuslineMode"] === "string")
|
|
13281
|
+
setAutonomy("statuslineMode", payload["statuslineMode"]);
|
|
13282
|
+
if (typeof payload["animationStyle"] === "string")
|
|
13283
|
+
setAutonomy("animationStyle", payload["animationStyle"]);
|
|
13284
|
+
if (typeof payload["showModelReasoning"] === "boolean")
|
|
13285
|
+
setAutonomy("showModelReasoning", payload["showModelReasoning"]);
|
|
13286
|
+
if (autonomyTouched) decrypted.autonomy = autonomyCfg;
|
|
13287
|
+
if (typeof payload["nextPrediction"] === "boolean")
|
|
13288
|
+
decrypted.nextPrediction = payload["nextPrediction"];
|
|
13289
|
+
if (typeof payload["uiLocale"] === "string") decrypted.uiLocale = payload["uiLocale"];
|
|
13290
|
+
if (Array.isArray(payload["fallbackModels"]))
|
|
13291
|
+
decrypted.fallbackModels = payload["fallbackModels"];
|
|
13292
|
+
if (payload["fallbackProfiles"] && typeof payload["fallbackProfiles"] === "object" && !Array.isArray(payload["fallbackProfiles"])) {
|
|
13293
|
+
decrypted.fallbackProfiles = payload["fallbackProfiles"];
|
|
13306
13294
|
}
|
|
13307
|
-
if (
|
|
13308
|
-
|
|
13295
|
+
if (Array.isArray(payload["favoriteModels"]))
|
|
13296
|
+
decrypted.favoriteModels = payload["favoriteModels"];
|
|
13297
|
+
if (typeof payload["favoriteModelsOnly"] === "boolean")
|
|
13298
|
+
decrypted.favoriteModelsOnly = payload["favoriteModelsOnly"];
|
|
13299
|
+
if (Array.isArray(payload["modelAvailabilitySchedule"]))
|
|
13300
|
+
decrypted.modelAvailabilitySchedule = payload["modelAvailabilitySchedule"];
|
|
13301
|
+
if (payload["modelMatrix"] && typeof payload["modelMatrix"] === "object" && !Array.isArray(payload["modelMatrix"])) {
|
|
13302
|
+
decrypted.modelMatrix = payload["modelMatrix"];
|
|
13303
|
+
}
|
|
13304
|
+
if (typeof payload["fallbackAuto"] === "boolean")
|
|
13305
|
+
decrypted.fallbackAuto = payload["fallbackAuto"];
|
|
13306
|
+
const FEATURE_MAP = {
|
|
13307
|
+
featureMcp: "mcp",
|
|
13308
|
+
featurePlugins: "plugins",
|
|
13309
|
+
featureMemory: "memory",
|
|
13310
|
+
featureSkills: "skills",
|
|
13311
|
+
featureModelsRegistry: "modelsRegistry"
|
|
13312
|
+
};
|
|
13313
|
+
for (const [prefKey, cfgKey] of Object.entries(FEATURE_MAP)) {
|
|
13314
|
+
if (typeof payload[prefKey] === "boolean") {
|
|
13315
|
+
const feats = decrypted.features ?? {};
|
|
13316
|
+
feats[cfgKey] = payload[prefKey];
|
|
13317
|
+
decrypted.features = feats;
|
|
13318
|
+
}
|
|
13319
|
+
}
|
|
13320
|
+
if (typeof payload["contextAutoCompact"] === "boolean" || typeof payload["contextStrategy"] === "string" || typeof payload["contextMode"] === "string") {
|
|
13321
|
+
const ctxCfg = decrypted.context ?? {};
|
|
13322
|
+
if (typeof payload["contextAutoCompact"] === "boolean")
|
|
13323
|
+
ctxCfg.autoCompact = payload["contextAutoCompact"];
|
|
13324
|
+
if (typeof payload["contextStrategy"] === "string")
|
|
13325
|
+
ctxCfg.strategy = payload["contextStrategy"];
|
|
13326
|
+
if (typeof payload["contextMode"] === "string") ctxCfg.mode = payload["contextMode"];
|
|
13327
|
+
decrypted.context = ctxCfg;
|
|
13328
|
+
}
|
|
13329
|
+
if (typeof payload["tokenSavingTier"] === "string") {
|
|
13330
|
+
const featsCfg = decrypted.features ?? {};
|
|
13331
|
+
featsCfg.tokenSavingMode = payload["tokenSavingTier"];
|
|
13332
|
+
decrypted.features = featsCfg;
|
|
13333
|
+
}
|
|
13334
|
+
if (typeof payload["maxConcurrent"] === "number") {
|
|
13335
|
+
decrypted.maxConcurrent = payload["maxConcurrent"];
|
|
13336
|
+
}
|
|
13337
|
+
if (typeof payload["titleAnimation"] === "boolean") {
|
|
13338
|
+
const autoCfg = decrypted.autonomy ?? {};
|
|
13339
|
+
autoCfg.terminalTitleAnimation = payload["titleAnimation"];
|
|
13340
|
+
decrypted.autonomy = autoCfg;
|
|
13309
13341
|
}
|
|
13310
|
-
if (typeof payload["
|
|
13311
|
-
|
|
13342
|
+
if (typeof payload["logLevel"] === "string") {
|
|
13343
|
+
const logCfg = decrypted.log ?? {};
|
|
13344
|
+
logCfg.level = payload["logLevel"];
|
|
13345
|
+
decrypted.log = logCfg;
|
|
13346
|
+
}
|
|
13347
|
+
if (typeof payload["auditLevel"] === "string") {
|
|
13348
|
+
const sessionCfg = decrypted.session ?? {};
|
|
13349
|
+
sessionCfg.auditLevel = payload["auditLevel"];
|
|
13350
|
+
decrypted.session = sessionCfg;
|
|
13351
|
+
}
|
|
13352
|
+
if (typeof payload["indexOnStart"] === "boolean") {
|
|
13353
|
+
const indexingCfg = decrypted.indexing ?? {};
|
|
13354
|
+
indexingCfg.onSessionStart = payload["indexOnStart"];
|
|
13355
|
+
decrypted.indexing = indexingCfg;
|
|
13356
|
+
}
|
|
13357
|
+
if (typeof payload["maxIterations"] === "number") {
|
|
13358
|
+
const toolsCfg = decrypted.tools ?? {};
|
|
13359
|
+
toolsCfg.maxIterations = payload["maxIterations"];
|
|
13360
|
+
decrypted.tools = toolsCfg;
|
|
13361
|
+
}
|
|
13362
|
+
const hqTouched = typeof payload["hqEnabled"] === "boolean" || typeof payload["hqUrl"] === "string" || typeof payload["hqToken"] === "string" || typeof payload["hqRawContent"] === "boolean";
|
|
13363
|
+
if (hqTouched) {
|
|
13364
|
+
const hqCfg = decrypted.hq ?? {};
|
|
13365
|
+
if (typeof payload["hqEnabled"] === "boolean") hqCfg.enabled = payload["hqEnabled"];
|
|
13366
|
+
if (typeof payload["hqUrl"] === "string") hqCfg.url = payload["hqUrl"];
|
|
13367
|
+
if (typeof payload["hqToken"] === "string") hqCfg.token = payload["hqToken"];
|
|
13368
|
+
if (typeof payload["hqRawContent"] === "boolean")
|
|
13369
|
+
hqCfg.rawContent = payload["hqRawContent"];
|
|
13370
|
+
decrypted.hq = hqCfg;
|
|
13371
|
+
}
|
|
13372
|
+
const tgTouched = typeof payload["tgSessionEnd"] === "boolean" || typeof payload["tgDelegate"] === "boolean" || typeof payload["tgLongToolMs"] === "number";
|
|
13373
|
+
if (tgTouched) {
|
|
13374
|
+
const ext = decrypted.extensions ?? {};
|
|
13375
|
+
const tg = ext["telegram"] ?? {};
|
|
13376
|
+
if (typeof payload["tgSessionEnd"] === "boolean") {
|
|
13377
|
+
tg["notifyOnSessionEnd"] = payload["tgSessionEnd"];
|
|
13378
|
+
}
|
|
13379
|
+
if (typeof payload["tgDelegate"] === "boolean") {
|
|
13380
|
+
tg["notifyOnDelegate"] = payload["tgDelegate"];
|
|
13381
|
+
}
|
|
13382
|
+
if (typeof payload["tgLongToolMs"] === "number") {
|
|
13383
|
+
tg["longToolThresholdMs"] = payload["tgLongToolMs"];
|
|
13384
|
+
}
|
|
13385
|
+
ext["telegram"] = tg;
|
|
13386
|
+
decrypted.extensions = ext;
|
|
13387
|
+
}
|
|
13388
|
+
const modelRuntimeTouched = typeof payload["reasoningMode"] === "string" || typeof payload["reasoningEffort"] === "string" || typeof payload["reasoningPreserve"] === "boolean" || typeof payload["cacheTtl"] === "string";
|
|
13389
|
+
if (modelRuntimeTouched) {
|
|
13390
|
+
const mr = decrypted.modelRuntime ?? {};
|
|
13391
|
+
const reasoning = mr.reasoning ?? {};
|
|
13392
|
+
if (typeof payload["reasoningMode"] === "string") reasoning.mode = payload["reasoningMode"];
|
|
13393
|
+
if (typeof payload["reasoningEffort"] === "string")
|
|
13394
|
+
reasoning.effort = payload["reasoningEffort"];
|
|
13395
|
+
if (typeof payload["reasoningPreserve"] === "boolean")
|
|
13396
|
+
reasoning.preserve = payload["reasoningPreserve"];
|
|
13397
|
+
mr.reasoning = reasoning;
|
|
13398
|
+
if (typeof payload["cacheTtl"] === "string" && payload["cacheTtl"] !== "default") {
|
|
13399
|
+
mr.cache = { ttl: payload["cacheTtl"] };
|
|
13400
|
+
} else if (payload["cacheTtl"] === "default") {
|
|
13401
|
+
delete mr.cache;
|
|
13402
|
+
}
|
|
13403
|
+
decrypted.modelRuntime = mr;
|
|
13312
13404
|
}
|
|
13313
|
-
if (typeof payload["
|
|
13314
|
-
|
|
13315
|
-
|
|
13405
|
+
if (typeof payload["breakerEnabled"] === "boolean" || typeof payload["breakerAutoKillResetMs"] === "number") {
|
|
13406
|
+
const cb = decrypted.circuitBreaker ?? {};
|
|
13407
|
+
if (typeof payload["breakerEnabled"] === "boolean") cb.enabled = payload["breakerEnabled"];
|
|
13408
|
+
if (typeof payload["breakerAutoKillResetMs"] === "number")
|
|
13409
|
+
cb.autoKillResetMs = payload["breakerAutoKillResetMs"];
|
|
13410
|
+
decrypted.circuitBreaker = cb;
|
|
13411
|
+
}
|
|
13412
|
+
if (payload["fsAccess"] === "unrestricted" || payload["fsAccess"] === "project") {
|
|
13413
|
+
const restrict = payload["fsAccess"] === "project";
|
|
13414
|
+
const toolsCfg = decrypted.tools ?? {};
|
|
13415
|
+
toolsCfg.restrictToProjectRoot = restrict;
|
|
13416
|
+
decrypted.tools = toolsCfg;
|
|
13417
|
+
const featsCfg = decrypted.features ?? {};
|
|
13418
|
+
featsCfg.allowOutsideProjectRoot = !restrict;
|
|
13419
|
+
decrypted.features = featsCfg;
|
|
13420
|
+
}
|
|
13421
|
+
if (typeof payload["debugStream"] === "boolean")
|
|
13422
|
+
decrypted.debugStream = payload["debugStream"];
|
|
13423
|
+
if (typeof payload["pluginsEnabled"] === "object" && payload["pluginsEnabled"] !== null) {
|
|
13424
|
+
const ext = decrypted.extensions ?? {};
|
|
13425
|
+
for (const [pluginName, enabled] of Object.entries(
|
|
13426
|
+
payload["pluginsEnabled"]
|
|
13427
|
+
)) {
|
|
13428
|
+
if (FORBIDDEN_PROTO_KEYS2.has(pluginName)) continue;
|
|
13429
|
+
const pExt = ext[pluginName] ?? {};
|
|
13430
|
+
pExt["enabled"] = enabled;
|
|
13431
|
+
ext[pluginName] = pExt;
|
|
13432
|
+
}
|
|
13433
|
+
decrypted.extensions = ext;
|
|
13434
|
+
}
|
|
13435
|
+
const chimeraTouched = typeof payload["chimeraEnabled"] === "boolean" || typeof payload["chimeraProvider"] === "string" || typeof payload["chimeraModel"] === "string" || typeof payload["chimeraMaxFiles"] === "number" || typeof payload["chimeraAutoFix"] === "string";
|
|
13436
|
+
if (chimeraTouched) {
|
|
13437
|
+
const ext = decrypted.extensions ?? {};
|
|
13438
|
+
const chimera = ext["wstack-chimera"] ?? {};
|
|
13439
|
+
if (typeof payload["chimeraEnabled"] === "boolean")
|
|
13440
|
+
chimera["enabled"] = payload["chimeraEnabled"];
|
|
13441
|
+
if (typeof payload["chimeraProvider"] === "string")
|
|
13442
|
+
chimera["provider"] = payload["chimeraProvider"];
|
|
13443
|
+
if (typeof payload["chimeraModel"] === "string") chimera["model"] = payload["chimeraModel"];
|
|
13444
|
+
if (typeof payload["chimeraMaxFiles"] === "number" && payload["chimeraMaxFiles"] >= 1) {
|
|
13445
|
+
chimera["maxFiles"] = payload["chimeraMaxFiles"];
|
|
13446
|
+
}
|
|
13447
|
+
if (typeof payload["chimeraAutoFix"] === "string") {
|
|
13448
|
+
if (payload["chimeraAutoFix"] === "off" || payload["chimeraAutoFix"] === "ask" || payload["chimeraAutoFix"] === "auto") {
|
|
13449
|
+
chimera["autoFix"] = payload["chimeraAutoFix"];
|
|
13450
|
+
}
|
|
13451
|
+
}
|
|
13452
|
+
ext["wstack-chimera"] = chimera;
|
|
13453
|
+
decrypted.extensions = ext;
|
|
13454
|
+
}
|
|
13455
|
+
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";
|
|
13456
|
+
if (autoReviewTouched) {
|
|
13457
|
+
const ext = decrypted.extensions ?? {};
|
|
13458
|
+
const ar = ext["wstack-auto-review"] ?? {};
|
|
13459
|
+
if (typeof payload["autoReviewEnabled"] === "boolean")
|
|
13460
|
+
ar["enabled"] = payload["autoReviewEnabled"];
|
|
13461
|
+
if (typeof payload["autoReviewProvider"] === "string")
|
|
13462
|
+
ar["provider"] = payload["autoReviewProvider"];
|
|
13463
|
+
if (typeof payload["autoReviewModel"] === "string")
|
|
13464
|
+
ar["model"] = payload["autoReviewModel"];
|
|
13465
|
+
if (typeof payload["autoReviewFallbackProfile"] === "string") {
|
|
13466
|
+
if (payload["autoReviewFallbackProfile"] === "") {
|
|
13467
|
+
delete ar["fallbackProfile"];
|
|
13468
|
+
} else {
|
|
13469
|
+
ar["fallbackProfile"] = payload["autoReviewFallbackProfile"];
|
|
13470
|
+
}
|
|
13471
|
+
}
|
|
13472
|
+
if (typeof payload["autoReviewDebounceMs"] === "number" && payload["autoReviewDebounceMs"] >= 0) {
|
|
13473
|
+
ar["debounceMs"] = payload["autoReviewDebounceMs"];
|
|
13474
|
+
}
|
|
13475
|
+
if (typeof payload["autoReviewMaxFilesPerBatch"] === "number" && payload["autoReviewMaxFilesPerBatch"] >= 1) {
|
|
13476
|
+
ar["maxFilesPerBatch"] = payload["autoReviewMaxFilesPerBatch"];
|
|
13477
|
+
}
|
|
13478
|
+
if (typeof payload["autoReviewMaxConcurrentReviews"] === "number" && payload["autoReviewMaxConcurrentReviews"] >= 1) {
|
|
13479
|
+
ar["maxConcurrentReviews"] = payload["autoReviewMaxConcurrentReviews"];
|
|
13480
|
+
}
|
|
13481
|
+
if (typeof payload["autoReviewCascadeOn"] === "string") {
|
|
13482
|
+
if (payload["autoReviewCascadeOn"] === "off" || payload["autoReviewCascadeOn"] === "critical" || payload["autoReviewCascadeOn"] === "high") {
|
|
13483
|
+
ar["cascadeOn"] = payload["autoReviewCascadeOn"];
|
|
13484
|
+
}
|
|
13316
13485
|
}
|
|
13486
|
+
ext["wstack-auto-review"] = ar;
|
|
13487
|
+
decrypted.extensions = ext;
|
|
13317
13488
|
}
|
|
13318
|
-
|
|
13319
|
-
|
|
13320
|
-
|
|
13321
|
-
}, "prefs");
|
|
13489
|
+
},
|
|
13490
|
+
"prefs"
|
|
13491
|
+
);
|
|
13322
13492
|
}
|
|
13323
13493
|
|
|
13324
13494
|
// src/server/provider-handlers.ts
|
|
@@ -13368,13 +13538,13 @@ async function probeModelDescriptors(cfg) {
|
|
|
13368
13538
|
}
|
|
13369
13539
|
}
|
|
13370
13540
|
function createProviderHandlers(deps2) {
|
|
13371
|
-
const { globalConfigPath, vault, broadcast: broadcast2, clients } = deps2;
|
|
13541
|
+
const { globalConfigPath, profileConfigPath, vault, broadcast: broadcast2, clients } = deps2;
|
|
13372
13542
|
let configWriteLock = deps2.getConfigWriteLock();
|
|
13373
13543
|
async function loadConfigProviders() {
|
|
13374
13544
|
return loadSavedProviders(globalConfigPath, vault);
|
|
13375
13545
|
}
|
|
13376
13546
|
async function saveConfigProviders(providers) {
|
|
13377
|
-
const next = configWriteLock.then(() => saveProviders(globalConfigPath, vault, providers)).catch((err) => {
|
|
13547
|
+
const next = configWriteLock.then(() => saveProviders(globalConfigPath, vault, providers, profileConfigPath)).catch((err) => {
|
|
13378
13548
|
const msg = toErrorMessage9(err);
|
|
13379
13549
|
console.error(JSON.stringify({
|
|
13380
13550
|
level: "error",
|
|
@@ -13649,13 +13819,14 @@ function createProviderHandlers(deps2) {
|
|
|
13649
13819
|
}
|
|
13650
13820
|
|
|
13651
13821
|
// src/server/routes.ts
|
|
13652
|
-
import
|
|
13822
|
+
import path22 from "node:path";
|
|
13653
13823
|
import {
|
|
13654
13824
|
buildRefinerContextSections,
|
|
13655
13825
|
enhanceUserPrompt,
|
|
13656
13826
|
gatedEnhancerReasoning,
|
|
13657
13827
|
nextEnhanceTimeout,
|
|
13658
13828
|
recentTextTurns,
|
|
13829
|
+
resolveConfiguredRefinerRef,
|
|
13659
13830
|
resolveEnhanceFallbackRef,
|
|
13660
13831
|
resolveProviderModelList
|
|
13661
13832
|
} from "@wrongstack/core";
|
|
@@ -13859,7 +14030,7 @@ function createModeHandlers(ctx) {
|
|
|
13859
14030
|
}
|
|
13860
14031
|
|
|
13861
14032
|
// src/server/project-handlers.ts
|
|
13862
|
-
import * as
|
|
14033
|
+
import * as path21 from "node:path";
|
|
13863
14034
|
function createProjectHandlers(ctx) {
|
|
13864
14035
|
return {
|
|
13865
14036
|
listProjects: async (ws) => {
|
|
@@ -13885,7 +14056,7 @@ function createProjectHandlers(ctx) {
|
|
|
13885
14056
|
selectProject: async (ws, msg) => {
|
|
13886
14057
|
const payload = msg.payload;
|
|
13887
14058
|
const root = typeof payload?.root === "string" ? payload.root : "";
|
|
13888
|
-
const name2 = typeof payload?.name === "string" ? payload.name : root ?
|
|
14059
|
+
const name2 = typeof payload?.name === "string" ? payload.name : root ? path21.basename(root) : "";
|
|
13889
14060
|
send(ws, {
|
|
13890
14061
|
type: "projects.selected",
|
|
13891
14062
|
payload: {
|
|
@@ -14339,7 +14510,9 @@ async function enrichProviderModelDescriptors(modelsRegistry, providerId, cfg, m
|
|
|
14339
14510
|
if (resolved.capabilities.vision) capabilities.add("vision");
|
|
14340
14511
|
return {
|
|
14341
14512
|
...model,
|
|
14342
|
-
contextWindow: model.contextWindow
|
|
14513
|
+
contextWindow: model.contextWindow ?? resolved.capabilities.maxContext ?? void 0,
|
|
14514
|
+
inputCost: model.inputCost ?? resolved.cost?.input,
|
|
14515
|
+
outputCost: model.outputCost ?? resolved.cost?.output,
|
|
14343
14516
|
capabilities: [...capabilities]
|
|
14344
14517
|
};
|
|
14345
14518
|
})
|
|
@@ -14348,6 +14521,7 @@ async function enrichProviderModelDescriptors(modelsRegistry, providerId, cfg, m
|
|
|
14348
14521
|
function buildRoutes(state, deps2, cb) {
|
|
14349
14522
|
const providerHandlers = createProviderHandlers({
|
|
14350
14523
|
globalConfigPath: deps2.globalConfigPath,
|
|
14524
|
+
profileConfigPath: deps2.profileConfigPath,
|
|
14351
14525
|
vault: deps2.vault,
|
|
14352
14526
|
getConfigWriteLock: state.getConfigWriteLock,
|
|
14353
14527
|
setConfigWriteLock: state.setConfigWriteLock,
|
|
@@ -14518,6 +14692,26 @@ function buildRoutes(state, deps2, cb) {
|
|
|
14518
14692
|
});
|
|
14519
14693
|
return;
|
|
14520
14694
|
}
|
|
14695
|
+
} else {
|
|
14696
|
+
const configuredRef = resolveConfiguredRefinerRef({
|
|
14697
|
+
...cfg,
|
|
14698
|
+
provider: providerId,
|
|
14699
|
+
model
|
|
14700
|
+
});
|
|
14701
|
+
if (configuredRef) {
|
|
14702
|
+
const slash = configuredRef.indexOf("/");
|
|
14703
|
+
const configuredProvider = slash > 0 ? configuredRef.slice(0, slash) : providerId;
|
|
14704
|
+
const configuredModel = slash > 0 ? configuredRef.slice(slash + 1) : configuredRef;
|
|
14705
|
+
try {
|
|
14706
|
+
const providerCfg = cfg.providers?.[configuredProvider] ?? {
|
|
14707
|
+
type: configuredProvider
|
|
14708
|
+
};
|
|
14709
|
+
provider = deps2.providerRegistry.has(configuredProvider) ? deps2.providerRegistry.create({ ...providerCfg, type: configuredProvider }) : makeProviderFromConfig2(configuredProvider, providerCfg);
|
|
14710
|
+
providerId = configuredProvider;
|
|
14711
|
+
model = configuredModel;
|
|
14712
|
+
} catch {
|
|
14713
|
+
}
|
|
14714
|
+
}
|
|
14521
14715
|
}
|
|
14522
14716
|
const baseTimeout = 9e4;
|
|
14523
14717
|
const timeoutMs = typeof payload.timeoutMs === "number" && payload.timeoutMs > 0 ? payload.timeoutMs : baseTimeout;
|
|
@@ -14704,19 +14898,27 @@ function buildRoutes(state, deps2, cb) {
|
|
|
14704
14898
|
cfg.favoriteModels = payload["favoriteModels"];
|
|
14705
14899
|
if (typeof payload["favoriteModelsOnly"] === "boolean")
|
|
14706
14900
|
cfg.favoriteModelsOnly = payload["favoriteModelsOnly"];
|
|
14901
|
+
if (Array.isArray(payload["modelAvailabilitySchedule"]))
|
|
14902
|
+
cfg.modelAvailabilitySchedule = payload["modelAvailabilitySchedule"];
|
|
14707
14903
|
if (payload["modelMatrix"] && typeof payload["modelMatrix"] === "object" && !Array.isArray(payload["modelMatrix"])) {
|
|
14708
14904
|
cfg.modelMatrix = payload["modelMatrix"];
|
|
14709
14905
|
}
|
|
14710
14906
|
if (typeof payload["fallbackAuto"] === "boolean") cfg.fallbackAuto = payload["fallbackAuto"];
|
|
14711
14907
|
const routingPatch = {};
|
|
14712
|
-
if (Array.isArray(payload["fallbackModels"]))
|
|
14908
|
+
if (Array.isArray(payload["fallbackModels"]))
|
|
14909
|
+
routingPatch.fallbackModels = payload["fallbackModels"];
|
|
14713
14910
|
if (payload["fallbackProfiles"] && typeof payload["fallbackProfiles"] === "object" && !Array.isArray(payload["fallbackProfiles"]))
|
|
14714
14911
|
routingPatch.fallbackProfiles = payload["fallbackProfiles"];
|
|
14715
|
-
if (Array.isArray(payload["favoriteModels"]))
|
|
14716
|
-
|
|
14912
|
+
if (Array.isArray(payload["favoriteModels"]))
|
|
14913
|
+
routingPatch.favoriteModels = payload["favoriteModels"];
|
|
14914
|
+
if (typeof payload["favoriteModelsOnly"] === "boolean")
|
|
14915
|
+
routingPatch.favoriteModelsOnly = payload["favoriteModelsOnly"];
|
|
14916
|
+
if (Array.isArray(payload["modelAvailabilitySchedule"]))
|
|
14917
|
+
routingPatch.modelAvailabilitySchedule = payload["modelAvailabilitySchedule"];
|
|
14717
14918
|
if (payload["modelMatrix"] && typeof payload["modelMatrix"] === "object" && !Array.isArray(payload["modelMatrix"]))
|
|
14718
14919
|
routingPatch.modelMatrix = payload["modelMatrix"];
|
|
14719
|
-
if (typeof payload["fallbackAuto"] === "boolean")
|
|
14920
|
+
if (typeof payload["fallbackAuto"] === "boolean")
|
|
14921
|
+
routingPatch.fallbackAuto = payload["fallbackAuto"];
|
|
14720
14922
|
if (Object.keys(routingPatch).length > 0)
|
|
14721
14923
|
deps2.configStore.update(routingPatch);
|
|
14722
14924
|
if (typeof payload["contextAutoCompact"] === "boolean") {
|
|
@@ -14787,7 +14989,7 @@ function buildRoutes(state, deps2, cb) {
|
|
|
14787
14989
|
}
|
|
14788
14990
|
return handleMailboxMessages(
|
|
14789
14991
|
ws,
|
|
14790
|
-
{ projectRoot: state.getProjectRoot(), globalRoot:
|
|
14992
|
+
{ projectRoot: state.getProjectRoot(), globalRoot: path22.dirname(deps2.globalConfigPath) },
|
|
14791
14993
|
parsed.value
|
|
14792
14994
|
);
|
|
14793
14995
|
},
|
|
@@ -14799,13 +15001,13 @@ function buildRoutes(state, deps2, cb) {
|
|
|
14799
15001
|
}
|
|
14800
15002
|
return handleMailboxAgents(
|
|
14801
15003
|
ws,
|
|
14802
|
-
{ projectRoot: state.getProjectRoot(), globalRoot:
|
|
15004
|
+
{ projectRoot: state.getProjectRoot(), globalRoot: path22.dirname(deps2.globalConfigPath) },
|
|
14803
15005
|
parsed.value
|
|
14804
15006
|
);
|
|
14805
15007
|
},
|
|
14806
15008
|
clear: (ws) => handleMailboxClear(ws, {
|
|
14807
15009
|
projectRoot: state.getProjectRoot(),
|
|
14808
|
-
globalRoot:
|
|
15010
|
+
globalRoot: path22.dirname(deps2.globalConfigPath)
|
|
14809
15011
|
}),
|
|
14810
15012
|
purge: (ws, msg) => {
|
|
14811
15013
|
const parsed = validateMailboxPurgePayload(msg.payload);
|
|
@@ -14815,14 +15017,14 @@ function buildRoutes(state, deps2, cb) {
|
|
|
14815
15017
|
}
|
|
14816
15018
|
return handleMailboxPurge(
|
|
14817
15019
|
ws,
|
|
14818
|
-
{ projectRoot: state.getProjectRoot(), globalRoot:
|
|
15020
|
+
{ projectRoot: state.getProjectRoot(), globalRoot: path22.dirname(deps2.globalConfigPath) },
|
|
14819
15021
|
parsed.value
|
|
14820
15022
|
);
|
|
14821
15023
|
},
|
|
14822
15024
|
compact: (ws, msg) => {
|
|
14823
15025
|
return handleMailboxCompact(
|
|
14824
15026
|
ws,
|
|
14825
|
-
{ projectRoot: state.getProjectRoot(), globalRoot:
|
|
15027
|
+
{ projectRoot: state.getProjectRoot(), globalRoot: path22.dirname(deps2.globalConfigPath) },
|
|
14826
15028
|
msg.payload ?? {}
|
|
14827
15029
|
);
|
|
14828
15030
|
}
|
|
@@ -14973,7 +15175,9 @@ async function startWebUI(opts = {}) {
|
|
|
14973
15175
|
let projectRoot = boot.projectRoot;
|
|
14974
15176
|
let workingDir = projectRoot;
|
|
14975
15177
|
const configWriteLock = { lock: Promise.resolve() };
|
|
14976
|
-
const
|
|
15178
|
+
const activeProfile = config.activeProfile ?? "default";
|
|
15179
|
+
const profileConfigPath = wpaths.profileConfig(activeProfile);
|
|
15180
|
+
const prefHelperDeps = { globalConfigPath, profileConfigPath, vault, logger };
|
|
14977
15181
|
const updateGlobalConfig2 = async (mutate, errorLabel) => updateGlobalConfig(prefHelperDeps, configWriteLock, mutate, errorLabel);
|
|
14978
15182
|
console.log("[WebUI] Config loaded:", config.provider ?? "(none)", "/", config.model ?? "(none)");
|
|
14979
15183
|
if (!config.provider && config.providers && typeof config.providers === "object" && config.providers !== null && !Array.isArray(config.providers) && Object.keys(config.providers).length > 0) {
|
|
@@ -15135,21 +15339,21 @@ async function startWebUI(opts = {}) {
|
|
|
15135
15339
|
wpaths
|
|
15136
15340
|
}, watcherMetricsRef);
|
|
15137
15341
|
async function touchProjectEntry(root, workDir) {
|
|
15138
|
-
const resolved =
|
|
15342
|
+
const resolved = path23.resolve(root);
|
|
15139
15343
|
const manifest = await loadManifest(globalConfigPath);
|
|
15140
15344
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
15141
|
-
const existing = manifest.projects.find((p) =>
|
|
15345
|
+
const existing = manifest.projects.find((p) => path23.resolve(p.root) === resolved);
|
|
15142
15346
|
if (existing) {
|
|
15143
15347
|
existing.lastSeen = now;
|
|
15144
|
-
if (workDir) existing.lastWorkingDir =
|
|
15348
|
+
if (workDir) existing.lastWorkingDir = path23.resolve(workDir);
|
|
15145
15349
|
} else {
|
|
15146
15350
|
manifest.projects.push({
|
|
15147
|
-
name:
|
|
15351
|
+
name: path23.basename(resolved),
|
|
15148
15352
|
root: resolved,
|
|
15149
15353
|
slug: generateProjectSlug(resolved),
|
|
15150
15354
|
createdAt: now,
|
|
15151
15355
|
lastSeen: now,
|
|
15152
|
-
lastWorkingDir: workDir ?
|
|
15356
|
+
lastWorkingDir: workDir ? path23.resolve(workDir) : void 0
|
|
15153
15357
|
});
|
|
15154
15358
|
}
|
|
15155
15359
|
await saveManifest(manifest, globalConfigPath);
|
|
@@ -15256,6 +15460,7 @@ async function startWebUI(opts = {}) {
|
|
|
15256
15460
|
persistPrefsToConfig: persistPrefsToConfig2,
|
|
15257
15461
|
prefSnapshot: prefSnapshot2
|
|
15258
15462
|
};
|
|
15463
|
+
const watchConfigPath = profileConfigPath ?? globalConfigPath;
|
|
15259
15464
|
let credentialWatcherClose;
|
|
15260
15465
|
if (process.env["WRONGSTACK_DISABLE_CONFIG_WATCH"] !== "1") {
|
|
15261
15466
|
let lastActiveCfg = JSON.stringify(
|
|
@@ -15263,7 +15468,7 @@ async function startWebUI(opts = {}) {
|
|
|
15263
15468
|
);
|
|
15264
15469
|
let lastUiLocale = state.getConfig().uiLocale;
|
|
15265
15470
|
const credentialWatcher = watchProviderConfig(
|
|
15266
|
-
|
|
15471
|
+
watchConfigPath,
|
|
15267
15472
|
vault,
|
|
15268
15473
|
(snapshot) => {
|
|
15269
15474
|
state.setConfig(
|
|
@@ -15404,7 +15609,7 @@ async function startWebUI(opts = {}) {
|
|
|
15404
15609
|
archiveLowConfidenceAfterDays: config.superMemory?.hygiene?.archiveLowConfidenceAfterDays
|
|
15405
15610
|
}).catch((err) => logger.warn(`super-memory session hygiene failed: ${toErrorMessage10(err)}`));
|
|
15406
15611
|
}
|
|
15407
|
-
await unregisterInstance(process.pid,
|
|
15612
|
+
await unregisterInstance(process.pid, path23.dirname(globalConfigPath));
|
|
15408
15613
|
}
|
|
15409
15614
|
});
|
|
15410
15615
|
}
|