@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/index.js
CHANGED
|
@@ -1809,15 +1809,15 @@ async function handleGitChanges(ws, projectRoot) {
|
|
|
1809
1809
|
if (!m) continue;
|
|
1810
1810
|
const added = m[1] === "-" ? 0 : Number(m[1]);
|
|
1811
1811
|
const deleted = m[2] === "-" ? 0 : Number(m[2]);
|
|
1812
|
-
let
|
|
1813
|
-
if (
|
|
1812
|
+
let path25 = m[3] ?? "";
|
|
1813
|
+
if (path25 === "") {
|
|
1814
1814
|
i += 1;
|
|
1815
|
-
|
|
1815
|
+
path25 = parts[i + 1] ?? parts[i] ?? "";
|
|
1816
1816
|
i += 1;
|
|
1817
1817
|
}
|
|
1818
|
-
if (!
|
|
1819
|
-
const prev = counts.get(
|
|
1820
|
-
counts.set(
|
|
1818
|
+
if (!path25) continue;
|
|
1819
|
+
const prev = counts.get(path25) ?? { added: 0, deleted: 0 };
|
|
1820
|
+
counts.set(path25, { added: prev.added + added, deleted: prev.deleted + deleted });
|
|
1821
1821
|
}
|
|
1822
1822
|
};
|
|
1823
1823
|
parseNumstat(unstagedNumstat);
|
|
@@ -1829,7 +1829,7 @@ async function handleGitChanges(ws, projectRoot) {
|
|
|
1829
1829
|
if (!rec || rec.length < 3) continue;
|
|
1830
1830
|
const x = rec[0] ?? " ";
|
|
1831
1831
|
const y = rec[1] ?? " ";
|
|
1832
|
-
const
|
|
1832
|
+
const path25 = rec.slice(3);
|
|
1833
1833
|
const isRename = x === "R" || x === "C" || y === "R" || y === "C";
|
|
1834
1834
|
if (isRename) i += 1;
|
|
1835
1835
|
let status;
|
|
@@ -1841,13 +1841,13 @@ async function handleGitChanges(ws, projectRoot) {
|
|
|
1841
1841
|
else if (x === "D" || y === "D") status = "D";
|
|
1842
1842
|
else status = "M";
|
|
1843
1843
|
const staged = x !== " " && x !== "?";
|
|
1844
|
-
let added = counts.get(
|
|
1845
|
-
let deleted = counts.get(
|
|
1844
|
+
let added = counts.get(path25)?.added ?? 0;
|
|
1845
|
+
let deleted = counts.get(path25)?.deleted ?? 0;
|
|
1846
1846
|
if (status === "?") {
|
|
1847
1847
|
added = 0;
|
|
1848
1848
|
deleted = 0;
|
|
1849
1849
|
}
|
|
1850
|
-
files.push({ path:
|
|
1850
|
+
files.push({ path: path25, status, added, deleted, staged });
|
|
1851
1851
|
}
|
|
1852
1852
|
send(ws, { type: "git.changes", payload: { files } });
|
|
1853
1853
|
} catch (err) {
|
|
@@ -1858,10 +1858,10 @@ async function handleGitChanges(ws, projectRoot) {
|
|
|
1858
1858
|
}
|
|
1859
1859
|
}
|
|
1860
1860
|
var MAX_DIFF_BYTES = 2 * 1024 * 1024;
|
|
1861
|
-
async function handleGitDiff(ws, projectRoot,
|
|
1861
|
+
async function handleGitDiff(ws, projectRoot, path25) {
|
|
1862
1862
|
const cwd = projectRoot || void 0;
|
|
1863
|
-
const reply = (extra) => send(ws, { type: "git.diff", payload: { path:
|
|
1864
|
-
if (!
|
|
1863
|
+
const reply = (extra) => send(ws, { type: "git.diff", payload: { path: path25, ...extra } });
|
|
1864
|
+
if (!path25 || path25.includes("\0") || path25.includes("..") || nodePath.isAbsolute(path25)) {
|
|
1865
1865
|
reply({ oldText: "", newText: "", error: "invalid path" });
|
|
1866
1866
|
return;
|
|
1867
1867
|
}
|
|
@@ -1869,10 +1869,10 @@ async function handleGitDiff(ws, projectRoot, path24) {
|
|
|
1869
1869
|
const git = makeGit(cwd);
|
|
1870
1870
|
const { readFile: readFile11 } = await import("node:fs/promises");
|
|
1871
1871
|
const { join: join15 } = await import("node:path");
|
|
1872
|
-
const oldText = await git(["show", `HEAD:${
|
|
1872
|
+
const oldText = await git(["show", `HEAD:${path25}`]);
|
|
1873
1873
|
let newText = "";
|
|
1874
1874
|
try {
|
|
1875
|
-
const abs = cwd ? join15(cwd,
|
|
1875
|
+
const abs = cwd ? join15(cwd, path25) : path25;
|
|
1876
1876
|
const buf = await readFile11(abs);
|
|
1877
1877
|
if (buf.includes(0)) {
|
|
1878
1878
|
reply({ oldText: "", newText: "", binary: true });
|
|
@@ -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");
|
|
@@ -3736,6 +3754,44 @@ async function handleSuperMemoryList(ws, memoryStore) {
|
|
|
3736
3754
|
send(ws, { type: "memory.super.list", payload: { error: errMessage(err) } });
|
|
3737
3755
|
}
|
|
3738
3756
|
}
|
|
3757
|
+
async function handleSuperMemoryListPage(ws, msg, memoryStore) {
|
|
3758
|
+
if (!isSuperMemoryStore(memoryStore)) {
|
|
3759
|
+
send(ws, { type: "memory.super.listPage", payload: { error: requiresSuperMemory("memory.super.listPage") } });
|
|
3760
|
+
return;
|
|
3761
|
+
}
|
|
3762
|
+
try {
|
|
3763
|
+
const payload = msg.payload ?? {};
|
|
3764
|
+
const options = {
|
|
3765
|
+
statuses: Array.isArray(payload["statuses"]) ? payload["statuses"].filter((s) => typeof s === "string") : void 0,
|
|
3766
|
+
kind: typeof payload["kind"] === "string" ? payload["kind"] : void 0,
|
|
3767
|
+
query: typeof payload["query"] === "string" ? payload["query"] : void 0,
|
|
3768
|
+
limit: typeof payload["limit"] === "number" ? payload["limit"] : void 0,
|
|
3769
|
+
cursor: typeof payload["cursor"] === "string" ? payload["cursor"] : void 0
|
|
3770
|
+
};
|
|
3771
|
+
if (typeof memoryStore.listSuperPage === "function") {
|
|
3772
|
+
const page = await memoryStore.listSuperPage(options);
|
|
3773
|
+
send(ws, { type: "memory.super.listPage", payload: page });
|
|
3774
|
+
return;
|
|
3775
|
+
}
|
|
3776
|
+
const allowed = options.statuses && options.statuses.length > 0 ? new Set(options.statuses) : void 0;
|
|
3777
|
+
const everything = await memoryStore.listSuper();
|
|
3778
|
+
const statusCounts = {};
|
|
3779
|
+
for (const m of everything) statusCounts[m.status] = (statusCounts[m.status] ?? 0) + 1;
|
|
3780
|
+
const kind = options.kind && options.kind !== "all" ? options.kind : void 0;
|
|
3781
|
+
const q = options.query?.trim().toLowerCase();
|
|
3782
|
+
const filtered = everything.filter((m) => {
|
|
3783
|
+
if (allowed) return allowed.has(m.status);
|
|
3784
|
+
return m.status !== "deleted";
|
|
3785
|
+
}).filter((m) => !kind || m.kind === kind).filter((m) => !q || m.text.toLowerCase().includes(q));
|
|
3786
|
+
const limit = Math.max(1, Math.min(500, Math.floor(options.limit ?? 50)));
|
|
3787
|
+
send(ws, {
|
|
3788
|
+
type: "memory.super.listPage",
|
|
3789
|
+
payload: { memories: filtered.slice(0, limit), nextCursor: null, total: filtered.length, statusCounts }
|
|
3790
|
+
});
|
|
3791
|
+
} catch (err) {
|
|
3792
|
+
send(ws, { type: "memory.super.listPage", payload: { error: errMessage(err) } });
|
|
3793
|
+
}
|
|
3794
|
+
}
|
|
3739
3795
|
async function handleSuperMemoryGet(ws, msg, memoryStore) {
|
|
3740
3796
|
if (!isSuperMemoryStore(memoryStore)) {
|
|
3741
3797
|
send(ws, { type: "memory.super.get", payload: { error: requiresSuperMemory("memory.super.get") } });
|
|
@@ -4299,7 +4355,7 @@ async function loadSavedProviders(configPath, vault) {
|
|
|
4299
4355
|
if (!parsed.providers) return {};
|
|
4300
4356
|
return decryptConfigSecrets(parsed.providers, vault);
|
|
4301
4357
|
}
|
|
4302
|
-
async function saveProviders(configPath, vault, providers) {
|
|
4358
|
+
async function saveProviders(configPath, vault, providers, profileConfigPath) {
|
|
4303
4359
|
let raw;
|
|
4304
4360
|
let fileExists = true;
|
|
4305
4361
|
try {
|
|
@@ -4333,6 +4389,23 @@ async function saveProviders(configPath, vault, providers) {
|
|
|
4333
4389
|
parsed.providers = providers;
|
|
4334
4390
|
const encrypted = encryptConfigSecrets(parsed, vault);
|
|
4335
4391
|
await atomicWrite4(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
4392
|
+
if (profileConfigPath && profileConfigPath !== configPath) {
|
|
4393
|
+
let profileRaw;
|
|
4394
|
+
try {
|
|
4395
|
+
profileRaw = await fs8.readFile(profileConfigPath, "utf8");
|
|
4396
|
+
} catch {
|
|
4397
|
+
profileRaw = "{}";
|
|
4398
|
+
}
|
|
4399
|
+
let profileParsed;
|
|
4400
|
+
try {
|
|
4401
|
+
profileParsed = JSON.parse(profileRaw);
|
|
4402
|
+
} catch {
|
|
4403
|
+
return;
|
|
4404
|
+
}
|
|
4405
|
+
profileParsed.providers = providers;
|
|
4406
|
+
const profileEncrypted = encryptConfigSecrets(profileParsed, vault);
|
|
4407
|
+
await atomicWrite4(profileConfigPath, JSON.stringify(profileEncrypted, null, 2), { mode: 384 });
|
|
4408
|
+
}
|
|
4336
4409
|
}
|
|
4337
4410
|
|
|
4338
4411
|
// src/server/provider-config-standalone.ts
|
|
@@ -5192,6 +5265,7 @@ var BOOLEAN_PREF_KEYS = /* @__PURE__ */ new Set([
|
|
|
5192
5265
|
"hqRawContent",
|
|
5193
5266
|
"fallbackAuto",
|
|
5194
5267
|
"favoriteModelsOnly",
|
|
5268
|
+
"modelAvailabilitySchedule",
|
|
5195
5269
|
"breakerEnabled",
|
|
5196
5270
|
"debugStream",
|
|
5197
5271
|
// Chimera + auto-review master toggles
|
|
@@ -5256,34 +5330,34 @@ var ENUM_PREF_KEYS = {
|
|
|
5256
5330
|
chimeraAutoFix: /* @__PURE__ */ new Set(["off", "ask", "auto"]),
|
|
5257
5331
|
autoReviewCascadeOn: /* @__PURE__ */ new Set(["off", "critical", "high"])
|
|
5258
5332
|
};
|
|
5259
|
-
function validateModelRuntimeValue(modelRuntime,
|
|
5333
|
+
function validateModelRuntimeValue(modelRuntime, path25) {
|
|
5260
5334
|
const reasoning = modelRuntime["reasoning"];
|
|
5261
5335
|
if (reasoning !== void 0) {
|
|
5262
|
-
if (!isRecord(reasoning)) return `${
|
|
5336
|
+
if (!isRecord(reasoning)) return `${path25}.reasoning must be an object when provided`;
|
|
5263
5337
|
const mode = reasoning["mode"];
|
|
5264
5338
|
const effort = reasoning["effort"];
|
|
5265
5339
|
const preserve = reasoning["preserve"];
|
|
5266
5340
|
if (mode !== void 0 && (typeof mode !== "string" || !REASONING_MODE_VALUES.has(mode))) {
|
|
5267
|
-
return `${
|
|
5341
|
+
return `${path25}.reasoning.mode must be one of: ${Array.from(REASONING_MODE_VALUES).join(", ")}`;
|
|
5268
5342
|
}
|
|
5269
5343
|
if (effort !== void 0 && (typeof effort !== "string" || !REASONING_EFFORT_VALUES.has(effort))) {
|
|
5270
|
-
return `${
|
|
5344
|
+
return `${path25}.reasoning.effort must be one of: ${Array.from(REASONING_EFFORT_VALUES).join(", ")}`;
|
|
5271
5345
|
}
|
|
5272
5346
|
if (preserve !== void 0 && typeof preserve !== "boolean") {
|
|
5273
|
-
return `${
|
|
5347
|
+
return `${path25}.reasoning.preserve must be a boolean when provided`;
|
|
5274
5348
|
}
|
|
5275
5349
|
}
|
|
5276
5350
|
const cache = modelRuntime["cache"];
|
|
5277
5351
|
if (cache !== void 0) {
|
|
5278
|
-
if (!isRecord(cache)) return `${
|
|
5352
|
+
if (!isRecord(cache)) return `${path25}.cache must be an object when provided`;
|
|
5279
5353
|
const ttl = cache["ttl"];
|
|
5280
5354
|
if (ttl !== void 0 && (typeof ttl !== "string" || !CACHE_TTL_VALUES.has(ttl) || ttl === "default")) {
|
|
5281
|
-
return `${
|
|
5355
|
+
return `${path25}.cache.ttl must be one of: 5m, 1h`;
|
|
5282
5356
|
}
|
|
5283
5357
|
}
|
|
5284
5358
|
const parameters = modelRuntime["parameters"];
|
|
5285
5359
|
if (parameters !== void 0 && !isRecord(parameters)) {
|
|
5286
|
-
return `${
|
|
5360
|
+
return `${path25}.parameters must be an object when provided`;
|
|
5287
5361
|
}
|
|
5288
5362
|
return null;
|
|
5289
5363
|
}
|
|
@@ -5336,7 +5410,10 @@ function validatePreferenceValue(key, value) {
|
|
|
5336
5410
|
return `prefs.update payload.${key}.modelRuntime must be an object when provided`;
|
|
5337
5411
|
}
|
|
5338
5412
|
if (isRecord(modelRuntime)) {
|
|
5339
|
-
const runtimeError = validateModelRuntimeValue(
|
|
5413
|
+
const runtimeError = validateModelRuntimeValue(
|
|
5414
|
+
modelRuntime,
|
|
5415
|
+
`prefs.update payload.${key}.modelRuntime`
|
|
5416
|
+
);
|
|
5340
5417
|
if (runtimeError) return runtimeError;
|
|
5341
5418
|
}
|
|
5342
5419
|
if (model === void 0 && fallbackProfile === void 0 && modelRuntime === void 0) {
|
|
@@ -5573,8 +5650,8 @@ function validateShellOpenPayload(payload) {
|
|
|
5573
5650
|
if (!isRecord(payload)) {
|
|
5574
5651
|
return { ok: false, message: "shell.open payload must be an object with string path" };
|
|
5575
5652
|
}
|
|
5576
|
-
const
|
|
5577
|
-
if (typeof
|
|
5653
|
+
const path25 = payload["path"];
|
|
5654
|
+
if (typeof path25 !== "string" || path25.trim().length === 0) {
|
|
5578
5655
|
return { ok: false, message: "shell.open payload.path must be a non-empty string" };
|
|
5579
5656
|
}
|
|
5580
5657
|
const target = payload["target"];
|
|
@@ -5587,7 +5664,7 @@ function validateShellOpenPayload(payload) {
|
|
|
5587
5664
|
return {
|
|
5588
5665
|
ok: true,
|
|
5589
5666
|
value: {
|
|
5590
|
-
path:
|
|
5667
|
+
path: path25,
|
|
5591
5668
|
...target !== void 0 ? { target } : {}
|
|
5592
5669
|
}
|
|
5593
5670
|
};
|
|
@@ -5596,14 +5673,14 @@ function validateGitDiffPayload(payload) {
|
|
|
5596
5673
|
if (!isRecord(payload)) {
|
|
5597
5674
|
return { ok: false, message: "git.diff payload must be an object" };
|
|
5598
5675
|
}
|
|
5599
|
-
const
|
|
5600
|
-
if (
|
|
5676
|
+
const path25 = payload["path"];
|
|
5677
|
+
if (path25 === void 0 || path25 === null) {
|
|
5601
5678
|
return { ok: true, value: { path: "" } };
|
|
5602
5679
|
}
|
|
5603
|
-
if (typeof
|
|
5680
|
+
if (typeof path25 !== "string") {
|
|
5604
5681
|
return { ok: false, message: "git.diff payload.path must be a string when provided" };
|
|
5605
5682
|
}
|
|
5606
|
-
return { ok: true, value: { path:
|
|
5683
|
+
return { ok: true, value: { path: path25 } };
|
|
5607
5684
|
}
|
|
5608
5685
|
function validateProjectsAddPayload(payload) {
|
|
5609
5686
|
if (!isRecord(payload)) {
|
|
@@ -6648,7 +6725,7 @@ function registerShutdownHandlers(res) {
|
|
|
6648
6725
|
import { watch as fsWatch } from "node:fs";
|
|
6649
6726
|
import * as fs11 from "node:fs/promises";
|
|
6650
6727
|
import * as path14 from "node:path";
|
|
6651
|
-
import { getBoard, getKanbanDir } from "@wrongstack/kanban";
|
|
6728
|
+
import { getBoard, getKanbanDir, recordTaskFileActivity } from "@wrongstack/kanban";
|
|
6652
6729
|
|
|
6653
6730
|
// src/server/codemap-telemetry.ts
|
|
6654
6731
|
import * as path13 from "node:path";
|
|
@@ -7044,6 +7121,18 @@ function setupEvents(deps2) {
|
|
|
7044
7121
|
on("file.activity", (e) => {
|
|
7045
7122
|
broadcast2(clients, { type: "codemap.file_event", payload: e });
|
|
7046
7123
|
});
|
|
7124
|
+
on("file.event", (e) => {
|
|
7125
|
+
if (e.scope !== "task" || !e.boardId || !e.taskId) return;
|
|
7126
|
+
void recordTaskFileActivity(context.projectRoot, e.boardId, e.taskId, e).then((recorded) => {
|
|
7127
|
+
if (recorded) {
|
|
7128
|
+
broadcast2(clients, {
|
|
7129
|
+
type: "kanban.task.activity.changed",
|
|
7130
|
+
payload: { boardId: e.boardId, taskId: e.taskId }
|
|
7131
|
+
});
|
|
7132
|
+
}
|
|
7133
|
+
}).catch(() => {
|
|
7134
|
+
});
|
|
7135
|
+
});
|
|
7047
7136
|
on("tool.loop_detected", (e) => {
|
|
7048
7137
|
broadcast2(clients, {
|
|
7049
7138
|
type: "tool.loop_detected",
|
|
@@ -7168,12 +7257,14 @@ function setupEvents(deps2) {
|
|
|
7168
7257
|
input: e.input,
|
|
7169
7258
|
suggestedPattern: e.suggestedPattern,
|
|
7170
7259
|
decisionSource: e.decisionSource,
|
|
7171
|
-
riskTier: e.riskTier
|
|
7260
|
+
riskTier: e.riskTier,
|
|
7261
|
+
boundaryReason: e.boundaryReason
|
|
7172
7262
|
});
|
|
7173
7263
|
pendingConfirms.set(id, {
|
|
7174
7264
|
resolve: e.resolve,
|
|
7175
7265
|
decisionSource: e.decisionSource,
|
|
7176
7266
|
riskTier: e.riskTier,
|
|
7267
|
+
boundaryReason: e.boundaryReason,
|
|
7177
7268
|
payload
|
|
7178
7269
|
});
|
|
7179
7270
|
broadcast2(clients, { type: "tool.confirm_needed", payload });
|
|
@@ -7266,7 +7357,8 @@ function setupEvents(deps2) {
|
|
|
7266
7357
|
oldState: e.oldState,
|
|
7267
7358
|
newState: e.newState,
|
|
7268
7359
|
reason: e.reason,
|
|
7269
|
-
timestamp: e.timestamp
|
|
7360
|
+
timestamp: e.timestamp,
|
|
7361
|
+
stateExpiresAt: e.stateExpiresAt
|
|
7270
7362
|
})
|
|
7271
7363
|
});
|
|
7272
7364
|
});
|
|
@@ -8373,6 +8465,7 @@ function seedContextMeta(config, context) {
|
|
|
8373
8465
|
meta["fallbackProfiles"] = config.fallbackProfiles ?? {};
|
|
8374
8466
|
meta["favoriteModels"] = config.favoriteModels ?? [];
|
|
8375
8467
|
meta["favoriteModelsOnly"] = config.favoriteModelsOnly === true;
|
|
8468
|
+
meta["modelAvailabilitySchedule"] = config.modelAvailabilitySchedule ?? [];
|
|
8376
8469
|
meta["modelMatrix"] = config.modelMatrix ?? {};
|
|
8377
8470
|
meta["fallbackAuto"] = config.fallbackAuto !== false;
|
|
8378
8471
|
if (typeof config.uiLocale === "string" && config.uiLocale) meta["uiLocale"] = config.uiLocale;
|
|
@@ -8455,9 +8548,7 @@ function seedContextMeta(config, context) {
|
|
|
8455
8548
|
} catch {
|
|
8456
8549
|
resolvedChain = [];
|
|
8457
8550
|
}
|
|
8458
|
-
meta["autoReviewFallbackModels"] = resolvedChain.map(
|
|
8459
|
-
(e) => `${e.providerId}/${e.model}`
|
|
8460
|
-
);
|
|
8551
|
+
meta["autoReviewFallbackModels"] = resolvedChain.map((e) => `${e.providerId}/${e.model}`);
|
|
8461
8552
|
}
|
|
8462
8553
|
}
|
|
8463
8554
|
|
|
@@ -8995,7 +9086,7 @@ function isSuperMemoryService(memoryStore) {
|
|
|
8995
9086
|
}
|
|
8996
9087
|
|
|
8997
9088
|
// src/server/start-webui.ts
|
|
8998
|
-
import * as
|
|
9089
|
+
import * as path24 from "node:path";
|
|
8999
9090
|
import {
|
|
9000
9091
|
createDefaultPipelines,
|
|
9001
9092
|
createSessionEventBridge,
|
|
@@ -9914,7 +10005,7 @@ function setupWebUICodebaseIndexing(deps2) {
|
|
|
9914
10005
|
}
|
|
9915
10006
|
if (idx) {
|
|
9916
10007
|
cancelPendingReindexes();
|
|
9917
|
-
shutdownCodebaseIndexHost();
|
|
10008
|
+
void shutdownCodebaseIndexHost();
|
|
9918
10009
|
}
|
|
9919
10010
|
}
|
|
9920
10011
|
};
|
|
@@ -10081,6 +10172,9 @@ var DEFAULT_COLS = 80;
|
|
|
10081
10172
|
var DEFAULT_ROWS = 24;
|
|
10082
10173
|
var requireFromHere = createRequire4(import.meta.url);
|
|
10083
10174
|
var cachedNodePty;
|
|
10175
|
+
function resolveTerminalShell(platform = process.platform, env = process.env) {
|
|
10176
|
+
return platform === "win32" ? env.COMSPEC || "cmd.exe" : env.SHELL || "/bin/sh";
|
|
10177
|
+
}
|
|
10084
10178
|
var TerminalWebSocketHandler = class {
|
|
10085
10179
|
constructor(getCwd, logger, loadNodePty = defaultLoadNodePty, killProcessTree = defaultKillProcessTree) {
|
|
10086
10180
|
this.getCwd = getCwd;
|
|
@@ -10136,7 +10230,7 @@ var TerminalWebSocketHandler = class {
|
|
|
10136
10230
|
});
|
|
10137
10231
|
return;
|
|
10138
10232
|
}
|
|
10139
|
-
const shell =
|
|
10233
|
+
const shell = resolveTerminalShell();
|
|
10140
10234
|
const nodePty = this.loadNodePty();
|
|
10141
10235
|
if (!nodePty) {
|
|
10142
10236
|
const msg = "Integrated terminal unavailable: optional dependency node-pty is not installed. Install node-pty to enable WebUI terminal sessions.";
|
|
@@ -10456,7 +10550,11 @@ async function createAgentServices(input) {
|
|
|
10456
10550
|
toolExecutor
|
|
10457
10551
|
});
|
|
10458
10552
|
if (config.features.memory && config.features.memoryConsolidation !== false) {
|
|
10459
|
-
|
|
10553
|
+
const consSuperMemory = typeof memoryStore["rememberSuper"] === "function" ? memoryStore : void 0;
|
|
10554
|
+
agent.extensions.register(new SessionMemoryConsolidator({
|
|
10555
|
+
memoryStore,
|
|
10556
|
+
...consSuperMemory ? { superMemory: consSuperMemory } : {}
|
|
10557
|
+
}));
|
|
10460
10558
|
}
|
|
10461
10559
|
console.log("[WebUI] Agent initialized");
|
|
10462
10560
|
const brainCfg = resolveBrainConfigDefaults(config.brain, {
|
|
@@ -10662,6 +10760,7 @@ function isSuperMemoryRetriever(memoryStore) {
|
|
|
10662
10760
|
// src/server/pending-confirms.ts
|
|
10663
10761
|
function resolveYoloEligiblePendingConfirms(pendingConfirms) {
|
|
10664
10762
|
for (const [id, confirm] of pendingConfirms) {
|
|
10763
|
+
if (confirm.boundaryReason) continue;
|
|
10665
10764
|
pendingConfirms.delete(id);
|
|
10666
10765
|
confirm.resolve("yes");
|
|
10667
10766
|
}
|
|
@@ -11141,7 +11240,7 @@ import {
|
|
|
11141
11240
|
createBoard,
|
|
11142
11241
|
duplicateBoard,
|
|
11143
11242
|
exportBoardToTaskGraph,
|
|
11144
|
-
|
|
11243
|
+
createBoardFromText,
|
|
11145
11244
|
getBoard as getBoard2,
|
|
11146
11245
|
getKanbanOrchestrationSnapshot,
|
|
11147
11246
|
getKanbanQueueHealth,
|
|
@@ -11172,6 +11271,32 @@ import {
|
|
|
11172
11271
|
updateTask
|
|
11173
11272
|
} from "@wrongstack/kanban";
|
|
11174
11273
|
import { applySessionKanbanTaskToSource } from "@wrongstack/tools/session-kanban";
|
|
11274
|
+
function paginateKanbanBoards(boards, input) {
|
|
11275
|
+
const pageSize = Math.min(100, Math.max(1, Math.floor(input.pageSize)));
|
|
11276
|
+
const activeSessionIds = new Set(input.activeSessionIds ?? []);
|
|
11277
|
+
const isActive = (board) => board.presence?.some((entry) => entry.active) === true || board.tags?.some(
|
|
11278
|
+
(tag) => tag.startsWith("session:") && activeSessionIds.has(tag.slice(8))
|
|
11279
|
+
) === true;
|
|
11280
|
+
const sorted = [...boards].sort((left, right) => {
|
|
11281
|
+
const activityOrder = Number(isActive(right)) - Number(isActive(left));
|
|
11282
|
+
return activityOrder || right.updatedAt.localeCompare(left.updatedAt);
|
|
11283
|
+
});
|
|
11284
|
+
const activeTotal = sorted.filter(isActive).length;
|
|
11285
|
+
const total = sorted.length;
|
|
11286
|
+
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
11287
|
+
const requestedPage = Number.isFinite(input.page) ? Math.floor(input.page) : 1;
|
|
11288
|
+
const page = Math.min(totalPages, Math.max(1, requestedPage));
|
|
11289
|
+
const start = (page - 1) * pageSize;
|
|
11290
|
+
return {
|
|
11291
|
+
items: sorted.slice(start, start + pageSize),
|
|
11292
|
+
total,
|
|
11293
|
+
page,
|
|
11294
|
+
pageSize,
|
|
11295
|
+
totalPages,
|
|
11296
|
+
activeTotal,
|
|
11297
|
+
orphanedTotal: total - activeTotal
|
|
11298
|
+
};
|
|
11299
|
+
}
|
|
11175
11300
|
async function syncSessionSource(ctx, task, remove = false) {
|
|
11176
11301
|
if (!ctx.context) return;
|
|
11177
11302
|
const update = await applySessionKanbanTaskToSource(ctx.context, task, { remove });
|
|
@@ -11221,9 +11346,26 @@ async function handleKanbanRoute(ws, msg, ctx) {
|
|
|
11221
11346
|
const type = msg.type;
|
|
11222
11347
|
try {
|
|
11223
11348
|
switch (type) {
|
|
11224
|
-
case "kanban.list":
|
|
11225
|
-
|
|
11349
|
+
case "kanban.list": {
|
|
11350
|
+
const boards = await listBoards(ctx.projectRoot);
|
|
11351
|
+
const requestedPage = Number(payload?.page);
|
|
11352
|
+
const requestedPageSize = Number(payload?.pageSize);
|
|
11353
|
+
if (!Number.isFinite(requestedPage) || !Number.isFinite(requestedPageSize)) {
|
|
11354
|
+
ok(ws, type, boards);
|
|
11355
|
+
return true;
|
|
11356
|
+
}
|
|
11357
|
+
const activeSessionIds = Array.isArray(payload?.activeSessionIds) ? payload.activeSessionIds.filter((id) => typeof id === "string") : [];
|
|
11358
|
+
ok(
|
|
11359
|
+
ws,
|
|
11360
|
+
type,
|
|
11361
|
+
paginateKanbanBoards(boards, {
|
|
11362
|
+
page: requestedPage,
|
|
11363
|
+
pageSize: requestedPageSize,
|
|
11364
|
+
activeSessionIds
|
|
11365
|
+
})
|
|
11366
|
+
);
|
|
11226
11367
|
return true;
|
|
11368
|
+
}
|
|
11227
11369
|
case "kanban.get": {
|
|
11228
11370
|
const boardId = payload?.boardId;
|
|
11229
11371
|
if (!boardId) {
|
|
@@ -11289,7 +11431,8 @@ async function handleKanbanRoute(ws, msg, ctx) {
|
|
|
11289
11431
|
...payload?.description ? { description: payload.description } : {},
|
|
11290
11432
|
...payload?.tags ? { tags: payload.tags } : {},
|
|
11291
11433
|
...payload?.columns ? { columns: payload.columns } : {},
|
|
11292
|
-
...has(payload, "lifecycle") ? { lifecycle: payload?.lifecycle } : {}
|
|
11434
|
+
...has(payload, "lifecycle") ? { lifecycle: payload?.lifecycle } : {},
|
|
11435
|
+
...has(payload, "boundary") ? { boundary: payload?.boundary } : {}
|
|
11293
11436
|
})
|
|
11294
11437
|
);
|
|
11295
11438
|
return true;
|
|
@@ -11310,6 +11453,9 @@ async function handleKanbanRoute(ws, msg, ctx) {
|
|
|
11310
11453
|
} : {},
|
|
11311
11454
|
...has(payload, "supervisor") ? {
|
|
11312
11455
|
supervisor: payload?.supervisor ?? null
|
|
11456
|
+
} : {},
|
|
11457
|
+
...has(payload, "boundary") ? {
|
|
11458
|
+
boundary: payload?.boundary ?? null
|
|
11313
11459
|
} : {}
|
|
11314
11460
|
});
|
|
11315
11461
|
board ? ok(ws, type, board) : fail(ws, type, `Board not found: ${boardId}`);
|
|
@@ -11356,7 +11502,7 @@ async function handleKanbanRoute(ws, msg, ctx) {
|
|
|
11356
11502
|
}
|
|
11357
11503
|
const board = await createBoard(
|
|
11358
11504
|
ctx.projectRoot,
|
|
11359
|
-
|
|
11505
|
+
createBoardFromText({
|
|
11360
11506
|
description,
|
|
11361
11507
|
...payload?.title ? { title: payload.title } : {},
|
|
11362
11508
|
...payload?.context ? { context: payload.context } : {}
|
|
@@ -11468,7 +11614,8 @@ async function handleKanbanRoute(ws, msg, ctx) {
|
|
|
11468
11614
|
...payload?.dueDate ? { dueDate: payload.dueDate } : {},
|
|
11469
11615
|
...payload?.priority ? { priority: payload.priority } : {},
|
|
11470
11616
|
...payload?.assignedAgent ? { assignedAgent: payload.assignedAgent } : {},
|
|
11471
|
-
...payload?.labels ? { labels: payload.labels } : {}
|
|
11617
|
+
...payload?.labels ? { labels: payload.labels } : {},
|
|
11618
|
+
...has(payload, "boundary") ? { boundary: payload?.boundary } : {}
|
|
11472
11619
|
},
|
|
11473
11620
|
activityContext(ctx, "webui", payload?.activityNote)
|
|
11474
11621
|
);
|
|
@@ -11549,6 +11696,9 @@ async function handleKanbanRoute(ws, msg, ctx) {
|
|
|
11549
11696
|
} : {},
|
|
11550
11697
|
...has(payload, "costCeilingUsd") ? {
|
|
11551
11698
|
costCeilingUsd: payload?.costCeilingUsd === null || payload?.costCeilingUsd === "" ? null : Number(payload?.costCeilingUsd)
|
|
11699
|
+
} : {},
|
|
11700
|
+
...has(payload, "boundary") ? {
|
|
11701
|
+
boundary: payload?.boundary ?? null
|
|
11552
11702
|
} : {}
|
|
11553
11703
|
},
|
|
11554
11704
|
activityContext(ctx, "webui", payload?.activityNote)
|
|
@@ -12441,7 +12591,7 @@ var chronicleCache = /* @__PURE__ */ new Map();
|
|
|
12441
12591
|
async function chronicleEngine(projectRoot) {
|
|
12442
12592
|
const now = Date.now();
|
|
12443
12593
|
const cached = chronicleCache.get(projectRoot);
|
|
12444
|
-
if (cached && now - cached.loadedAt <
|
|
12594
|
+
if (cached && now - cached.loadedAt < 6e4) return cached.engine;
|
|
12445
12595
|
const paths = resolveWstackPaths2({ projectRoot, userHome: os2.homedir() });
|
|
12446
12596
|
const engine = await ChronicleQueryEngine.fromDirectory(
|
|
12447
12597
|
path20.join(paths.projectDir, "chronicle")
|
|
@@ -12704,6 +12854,8 @@ function createMessageDispatcher(opts) {
|
|
|
12704
12854
|
// ── SuperMemory operations ──
|
|
12705
12855
|
case "memory.super.list":
|
|
12706
12856
|
return handleSuperMemoryList(ws, deps2.memoryStore);
|
|
12857
|
+
case "memory.super.listPage":
|
|
12858
|
+
return handleSuperMemoryListPage(ws, msg, deps2.memoryStore);
|
|
12707
12859
|
case "memory.super.get":
|
|
12708
12860
|
return handleSuperMemoryGet(ws, msg, deps2.memoryStore);
|
|
12709
12861
|
case "memory.super.update":
|
|
@@ -12958,7 +13110,7 @@ function createMessageDispatcher(opts) {
|
|
|
12958
13110
|
case "chronicle.query": {
|
|
12959
13111
|
const payload = msg.payload ?? {};
|
|
12960
13112
|
const engine = await chronicleEngine(state.getProjectRoot());
|
|
12961
|
-
send(ws, { type: "chronicle.query_result", payload: engine.query(payload.query ?? {}) });
|
|
13113
|
+
send(ws, { type: "chronicle.query_result", payload: await engine.query(payload.query ?? {}) });
|
|
12962
13114
|
break;
|
|
12963
13115
|
}
|
|
12964
13116
|
case "chronicle.facet": {
|
|
@@ -12988,7 +13140,7 @@ function createMessageDispatcher(opts) {
|
|
|
12988
13140
|
type: "chronicle.facet_result",
|
|
12989
13141
|
payload: {
|
|
12990
13142
|
field: payload.field,
|
|
12991
|
-
values: engine.facet(payload.field, payload.query ?? {}, payload.limit),
|
|
13143
|
+
values: await engine.facet(payload.field, payload.query ?? {}, payload.limit),
|
|
12992
13144
|
diagnostics: engine.diagnostics
|
|
12993
13145
|
}
|
|
12994
13146
|
});
|
|
@@ -12999,7 +13151,7 @@ function createMessageDispatcher(opts) {
|
|
|
12999
13151
|
const engine = await chronicleEngine(state.getProjectRoot());
|
|
13000
13152
|
send(ws, {
|
|
13001
13153
|
type: "chronicle.graph_result",
|
|
13002
|
-
payload: engine.graph(payload.seed ?? {}, payload.hops, payload.maxNodes)
|
|
13154
|
+
payload: await engine.graph(payload.seed ?? {}, payload.hops, payload.maxNodes)
|
|
13003
13155
|
});
|
|
13004
13156
|
break;
|
|
13005
13157
|
}
|
|
@@ -13054,9 +13206,10 @@ function createMessageDispatcher(opts) {
|
|
|
13054
13206
|
}
|
|
13055
13207
|
|
|
13056
13208
|
// 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
13209
|
import * as fs14 from "node:fs/promises";
|
|
13210
|
+
import * as path21 from "node:path";
|
|
13211
|
+
import { decryptConfigSecrets as decryptConfigSecrets2, encryptConfigSecrets as encryptConfigSecrets2 } from "@wrongstack/core/security";
|
|
13212
|
+
import { atomicWrite as atomicWrite6, backupConfigFile, FORBIDDEN_PROTO_KEYS as FORBIDDEN_PROTO_KEYS2 } from "@wrongstack/core/utils";
|
|
13060
13213
|
var PREF_KEYS = [
|
|
13061
13214
|
"autonomy",
|
|
13062
13215
|
"autonomyDelayMs",
|
|
@@ -13101,6 +13254,7 @@ var PREF_KEYS = [
|
|
|
13101
13254
|
"fallbackProfiles",
|
|
13102
13255
|
"favoriteModels",
|
|
13103
13256
|
"favoriteModelsOnly",
|
|
13257
|
+
"modelAvailabilitySchedule",
|
|
13104
13258
|
"modelMatrix",
|
|
13105
13259
|
"fallbackAuto",
|
|
13106
13260
|
// Refiner + TUI visual prefs (parity with the CLI's embedded server —
|
|
@@ -13144,26 +13298,34 @@ function prefSnapshot(contextMeta) {
|
|
|
13144
13298
|
}
|
|
13145
13299
|
return snapshot;
|
|
13146
13300
|
}
|
|
13301
|
+
async function writeGlobalConfigFile(filePath, vault, mutate, logger, errorLabel) {
|
|
13302
|
+
const globalRoot = path21.dirname(filePath);
|
|
13303
|
+
await backupConfigFile(filePath, { globalRoot });
|
|
13304
|
+
let raw;
|
|
13305
|
+
try {
|
|
13306
|
+
raw = await fs14.readFile(filePath, "utf8");
|
|
13307
|
+
} catch {
|
|
13308
|
+
raw = "{}";
|
|
13309
|
+
}
|
|
13310
|
+
let parsed;
|
|
13311
|
+
try {
|
|
13312
|
+
parsed = JSON.parse(raw);
|
|
13313
|
+
} catch {
|
|
13314
|
+
logger.warn(`${errorLabel}: refusing to overwrite corrupt config at ${filePath}`);
|
|
13315
|
+
return;
|
|
13316
|
+
}
|
|
13317
|
+
const decrypted = decryptConfigSecrets2(parsed, vault);
|
|
13318
|
+
mutate(decrypted);
|
|
13319
|
+
const encrypted = encryptConfigSecrets2(decrypted, vault);
|
|
13320
|
+
await atomicWrite6(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
13321
|
+
}
|
|
13147
13322
|
async function updateGlobalConfig(deps2, holder, mutate, errorLabel) {
|
|
13148
|
-
const { globalConfigPath, vault, logger } = deps2;
|
|
13323
|
+
const { globalConfigPath, profileConfigPath, vault, logger } = deps2;
|
|
13149
13324
|
const write = async () => {
|
|
13150
|
-
|
|
13151
|
-
|
|
13152
|
-
|
|
13153
|
-
} catch {
|
|
13154
|
-
raw = "{}";
|
|
13325
|
+
await writeGlobalConfigFile(globalConfigPath, vault, mutate, logger, errorLabel);
|
|
13326
|
+
if (profileConfigPath && profileConfigPath !== globalConfigPath) {
|
|
13327
|
+
await writeGlobalConfigFile(profileConfigPath, vault, mutate, logger, errorLabel);
|
|
13155
13328
|
}
|
|
13156
|
-
let parsed;
|
|
13157
|
-
try {
|
|
13158
|
-
parsed = JSON.parse(raw);
|
|
13159
|
-
} catch {
|
|
13160
|
-
logger.warn(`${errorLabel}: refusing to overwrite corrupt config at ${globalConfigPath}`);
|
|
13161
|
-
return;
|
|
13162
|
-
}
|
|
13163
|
-
const decrypted = decryptConfigSecrets2(parsed, vault);
|
|
13164
|
-
mutate(decrypted);
|
|
13165
|
-
const encrypted = encryptConfigSecrets2(decrypted, vault);
|
|
13166
|
-
await atomicWrite6(globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
13167
13329
|
};
|
|
13168
13330
|
const next = holder.lock.then(write);
|
|
13169
13331
|
holder.lock = next.then(
|
|
@@ -13173,256 +13335,264 @@ async function updateGlobalConfig(deps2, holder, mutate, errorLabel) {
|
|
|
13173
13335
|
try {
|
|
13174
13336
|
await next;
|
|
13175
13337
|
} catch (err) {
|
|
13176
|
-
logger.warn(
|
|
13338
|
+
logger.warn(
|
|
13339
|
+
`${errorLabel}: failed to persist to config: ${err instanceof Error ? err.message : String(err)}`
|
|
13340
|
+
);
|
|
13177
13341
|
}
|
|
13178
13342
|
}
|
|
13179
13343
|
async function persistPrefsToConfig(deps2, holder, payload) {
|
|
13180
|
-
return updateGlobalConfig(
|
|
13181
|
-
|
|
13182
|
-
|
|
13183
|
-
|
|
13184
|
-
autonomyCfg
|
|
13185
|
-
autonomyTouched =
|
|
13186
|
-
|
|
13187
|
-
|
|
13188
|
-
|
|
13189
|
-
|
|
13190
|
-
|
|
13191
|
-
|
|
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
|
-
}
|
|
13344
|
+
return updateGlobalConfig(
|
|
13345
|
+
deps2,
|
|
13346
|
+
holder,
|
|
13347
|
+
(decrypted) => {
|
|
13348
|
+
const autonomyCfg = decrypted.autonomy ?? {};
|
|
13349
|
+
let autonomyTouched = false;
|
|
13350
|
+
const setAutonomy = (key, val) => {
|
|
13351
|
+
autonomyCfg[key] = val;
|
|
13352
|
+
autonomyTouched = true;
|
|
13353
|
+
};
|
|
13354
|
+
if (typeof payload["autonomy"] === "string" && ["off", "suggest", "auto"].includes(payload["autonomy"])) {
|
|
13355
|
+
setAutonomy("defaultMode", payload["autonomy"]);
|
|
13407
13356
|
}
|
|
13408
|
-
if (typeof payload["
|
|
13409
|
-
|
|
13357
|
+
if (typeof payload["autonomyDelayMs"] === "number")
|
|
13358
|
+
setAutonomy("autoProceedDelayMs", payload["autonomyDelayMs"]);
|
|
13359
|
+
if (typeof payload["autoProceedMaxIterations"] === "number")
|
|
13360
|
+
setAutonomy("autoProceedMaxIterations", payload["autoProceedMaxIterations"]);
|
|
13361
|
+
if (typeof payload["yolo"] === "boolean") {
|
|
13362
|
+
setAutonomy("yolo", payload["yolo"]);
|
|
13363
|
+
decrypted.yolo = payload["yolo"];
|
|
13364
|
+
}
|
|
13365
|
+
if (typeof payload["chime"] === "boolean") setAutonomy("chime", payload["chime"]);
|
|
13366
|
+
if (typeof payload["confirmExit"] === "boolean")
|
|
13367
|
+
setAutonomy("confirmExit", payload["confirmExit"]);
|
|
13368
|
+
if (typeof payload["streamFleet"] === "boolean")
|
|
13369
|
+
setAutonomy("streamFleet", payload["streamFleet"]);
|
|
13370
|
+
if (typeof payload["enhanceEnabled"] === "boolean")
|
|
13371
|
+
setAutonomy("enhance", payload["enhanceEnabled"]);
|
|
13372
|
+
if (typeof payload["enhanceDelayMs"] === "number")
|
|
13373
|
+
setAutonomy("enhanceDelayMs", payload["enhanceDelayMs"]);
|
|
13374
|
+
if (typeof payload["enhanceLanguage"] === "string")
|
|
13375
|
+
setAutonomy("enhanceLanguage", payload["enhanceLanguage"]);
|
|
13376
|
+
if (typeof payload["refinerProvider"] === "string")
|
|
13377
|
+
setAutonomy("refinerProvider", payload["refinerProvider"]);
|
|
13378
|
+
if (typeof payload["refinerModel"] === "string")
|
|
13379
|
+
setAutonomy("refinerModel", payload["refinerModel"]);
|
|
13380
|
+
if (typeof payload["refinerFallbackProfile"] === "string")
|
|
13381
|
+
setAutonomy("refinerFallbackProfile", payload["refinerFallbackProfile"]);
|
|
13382
|
+
if (typeof payload["thinkingWord"] === "string")
|
|
13383
|
+
setAutonomy("thinkingWord", payload["thinkingWord"]);
|
|
13384
|
+
if (typeof payload["statuslineMode"] === "string")
|
|
13385
|
+
setAutonomy("statuslineMode", payload["statuslineMode"]);
|
|
13386
|
+
if (typeof payload["animationStyle"] === "string")
|
|
13387
|
+
setAutonomy("animationStyle", payload["animationStyle"]);
|
|
13388
|
+
if (typeof payload["showModelReasoning"] === "boolean")
|
|
13389
|
+
setAutonomy("showModelReasoning", payload["showModelReasoning"]);
|
|
13390
|
+
if (autonomyTouched) decrypted.autonomy = autonomyCfg;
|
|
13391
|
+
if (typeof payload["nextPrediction"] === "boolean")
|
|
13392
|
+
decrypted.nextPrediction = payload["nextPrediction"];
|
|
13393
|
+
if (typeof payload["uiLocale"] === "string") decrypted.uiLocale = payload["uiLocale"];
|
|
13394
|
+
if (Array.isArray(payload["fallbackModels"]))
|
|
13395
|
+
decrypted.fallbackModels = payload["fallbackModels"];
|
|
13396
|
+
if (payload["fallbackProfiles"] && typeof payload["fallbackProfiles"] === "object" && !Array.isArray(payload["fallbackProfiles"])) {
|
|
13397
|
+
decrypted.fallbackProfiles = payload["fallbackProfiles"];
|
|
13410
13398
|
}
|
|
13411
|
-
if (
|
|
13412
|
-
|
|
13399
|
+
if (Array.isArray(payload["favoriteModels"]))
|
|
13400
|
+
decrypted.favoriteModels = payload["favoriteModels"];
|
|
13401
|
+
if (typeof payload["favoriteModelsOnly"] === "boolean")
|
|
13402
|
+
decrypted.favoriteModelsOnly = payload["favoriteModelsOnly"];
|
|
13403
|
+
if (Array.isArray(payload["modelAvailabilitySchedule"]))
|
|
13404
|
+
decrypted.modelAvailabilitySchedule = payload["modelAvailabilitySchedule"];
|
|
13405
|
+
if (payload["modelMatrix"] && typeof payload["modelMatrix"] === "object" && !Array.isArray(payload["modelMatrix"])) {
|
|
13406
|
+
decrypted.modelMatrix = payload["modelMatrix"];
|
|
13407
|
+
}
|
|
13408
|
+
if (typeof payload["fallbackAuto"] === "boolean")
|
|
13409
|
+
decrypted.fallbackAuto = payload["fallbackAuto"];
|
|
13410
|
+
const FEATURE_MAP = {
|
|
13411
|
+
featureMcp: "mcp",
|
|
13412
|
+
featurePlugins: "plugins",
|
|
13413
|
+
featureMemory: "memory",
|
|
13414
|
+
featureSkills: "skills",
|
|
13415
|
+
featureModelsRegistry: "modelsRegistry"
|
|
13416
|
+
};
|
|
13417
|
+
for (const [prefKey, cfgKey] of Object.entries(FEATURE_MAP)) {
|
|
13418
|
+
if (typeof payload[prefKey] === "boolean") {
|
|
13419
|
+
const feats = decrypted.features ?? {};
|
|
13420
|
+
feats[cfgKey] = payload[prefKey];
|
|
13421
|
+
decrypted.features = feats;
|
|
13422
|
+
}
|
|
13423
|
+
}
|
|
13424
|
+
if (typeof payload["contextAutoCompact"] === "boolean" || typeof payload["contextStrategy"] === "string" || typeof payload["contextMode"] === "string") {
|
|
13425
|
+
const ctxCfg = decrypted.context ?? {};
|
|
13426
|
+
if (typeof payload["contextAutoCompact"] === "boolean")
|
|
13427
|
+
ctxCfg.autoCompact = payload["contextAutoCompact"];
|
|
13428
|
+
if (typeof payload["contextStrategy"] === "string")
|
|
13429
|
+
ctxCfg.strategy = payload["contextStrategy"];
|
|
13430
|
+
if (typeof payload["contextMode"] === "string") ctxCfg.mode = payload["contextMode"];
|
|
13431
|
+
decrypted.context = ctxCfg;
|
|
13432
|
+
}
|
|
13433
|
+
if (typeof payload["tokenSavingTier"] === "string") {
|
|
13434
|
+
const featsCfg = decrypted.features ?? {};
|
|
13435
|
+
featsCfg.tokenSavingMode = payload["tokenSavingTier"];
|
|
13436
|
+
decrypted.features = featsCfg;
|
|
13437
|
+
}
|
|
13438
|
+
if (typeof payload["maxConcurrent"] === "number") {
|
|
13439
|
+
decrypted.maxConcurrent = payload["maxConcurrent"];
|
|
13440
|
+
}
|
|
13441
|
+
if (typeof payload["titleAnimation"] === "boolean") {
|
|
13442
|
+
const autoCfg = decrypted.autonomy ?? {};
|
|
13443
|
+
autoCfg.terminalTitleAnimation = payload["titleAnimation"];
|
|
13444
|
+
decrypted.autonomy = autoCfg;
|
|
13413
13445
|
}
|
|
13414
|
-
if (typeof payload["
|
|
13415
|
-
|
|
13446
|
+
if (typeof payload["logLevel"] === "string") {
|
|
13447
|
+
const logCfg = decrypted.log ?? {};
|
|
13448
|
+
logCfg.level = payload["logLevel"];
|
|
13449
|
+
decrypted.log = logCfg;
|
|
13450
|
+
}
|
|
13451
|
+
if (typeof payload["auditLevel"] === "string") {
|
|
13452
|
+
const sessionCfg = decrypted.session ?? {};
|
|
13453
|
+
sessionCfg.auditLevel = payload["auditLevel"];
|
|
13454
|
+
decrypted.session = sessionCfg;
|
|
13455
|
+
}
|
|
13456
|
+
if (typeof payload["indexOnStart"] === "boolean") {
|
|
13457
|
+
const indexingCfg = decrypted.indexing ?? {};
|
|
13458
|
+
indexingCfg.onSessionStart = payload["indexOnStart"];
|
|
13459
|
+
decrypted.indexing = indexingCfg;
|
|
13460
|
+
}
|
|
13461
|
+
if (typeof payload["maxIterations"] === "number") {
|
|
13462
|
+
const toolsCfg = decrypted.tools ?? {};
|
|
13463
|
+
toolsCfg.maxIterations = payload["maxIterations"];
|
|
13464
|
+
decrypted.tools = toolsCfg;
|
|
13465
|
+
}
|
|
13466
|
+
const hqTouched = typeof payload["hqEnabled"] === "boolean" || typeof payload["hqUrl"] === "string" || typeof payload["hqToken"] === "string" || typeof payload["hqRawContent"] === "boolean";
|
|
13467
|
+
if (hqTouched) {
|
|
13468
|
+
const hqCfg = decrypted.hq ?? {};
|
|
13469
|
+
if (typeof payload["hqEnabled"] === "boolean") hqCfg.enabled = payload["hqEnabled"];
|
|
13470
|
+
if (typeof payload["hqUrl"] === "string") hqCfg.url = payload["hqUrl"];
|
|
13471
|
+
if (typeof payload["hqToken"] === "string") hqCfg.token = payload["hqToken"];
|
|
13472
|
+
if (typeof payload["hqRawContent"] === "boolean")
|
|
13473
|
+
hqCfg.rawContent = payload["hqRawContent"];
|
|
13474
|
+
decrypted.hq = hqCfg;
|
|
13475
|
+
}
|
|
13476
|
+
const tgTouched = typeof payload["tgSessionEnd"] === "boolean" || typeof payload["tgDelegate"] === "boolean" || typeof payload["tgLongToolMs"] === "number";
|
|
13477
|
+
if (tgTouched) {
|
|
13478
|
+
const ext = decrypted.extensions ?? {};
|
|
13479
|
+
const tg = ext["telegram"] ?? {};
|
|
13480
|
+
if (typeof payload["tgSessionEnd"] === "boolean") {
|
|
13481
|
+
tg["notifyOnSessionEnd"] = payload["tgSessionEnd"];
|
|
13482
|
+
}
|
|
13483
|
+
if (typeof payload["tgDelegate"] === "boolean") {
|
|
13484
|
+
tg["notifyOnDelegate"] = payload["tgDelegate"];
|
|
13485
|
+
}
|
|
13486
|
+
if (typeof payload["tgLongToolMs"] === "number") {
|
|
13487
|
+
tg["longToolThresholdMs"] = payload["tgLongToolMs"];
|
|
13488
|
+
}
|
|
13489
|
+
ext["telegram"] = tg;
|
|
13490
|
+
decrypted.extensions = ext;
|
|
13491
|
+
}
|
|
13492
|
+
const modelRuntimeTouched = typeof payload["reasoningMode"] === "string" || typeof payload["reasoningEffort"] === "string" || typeof payload["reasoningPreserve"] === "boolean" || typeof payload["cacheTtl"] === "string";
|
|
13493
|
+
if (modelRuntimeTouched) {
|
|
13494
|
+
const mr = decrypted.modelRuntime ?? {};
|
|
13495
|
+
const reasoning = mr.reasoning ?? {};
|
|
13496
|
+
if (typeof payload["reasoningMode"] === "string") reasoning.mode = payload["reasoningMode"];
|
|
13497
|
+
if (typeof payload["reasoningEffort"] === "string")
|
|
13498
|
+
reasoning.effort = payload["reasoningEffort"];
|
|
13499
|
+
if (typeof payload["reasoningPreserve"] === "boolean")
|
|
13500
|
+
reasoning.preserve = payload["reasoningPreserve"];
|
|
13501
|
+
mr.reasoning = reasoning;
|
|
13502
|
+
if (typeof payload["cacheTtl"] === "string" && payload["cacheTtl"] !== "default") {
|
|
13503
|
+
mr.cache = { ttl: payload["cacheTtl"] };
|
|
13504
|
+
} else if (payload["cacheTtl"] === "default") {
|
|
13505
|
+
delete mr.cache;
|
|
13506
|
+
}
|
|
13507
|
+
decrypted.modelRuntime = mr;
|
|
13416
13508
|
}
|
|
13417
|
-
if (typeof payload["
|
|
13418
|
-
|
|
13419
|
-
|
|
13509
|
+
if (typeof payload["breakerEnabled"] === "boolean" || typeof payload["breakerAutoKillResetMs"] === "number") {
|
|
13510
|
+
const cb = decrypted.circuitBreaker ?? {};
|
|
13511
|
+
if (typeof payload["breakerEnabled"] === "boolean") cb.enabled = payload["breakerEnabled"];
|
|
13512
|
+
if (typeof payload["breakerAutoKillResetMs"] === "number")
|
|
13513
|
+
cb.autoKillResetMs = payload["breakerAutoKillResetMs"];
|
|
13514
|
+
decrypted.circuitBreaker = cb;
|
|
13515
|
+
}
|
|
13516
|
+
if (payload["fsAccess"] === "unrestricted" || payload["fsAccess"] === "project") {
|
|
13517
|
+
const restrict = payload["fsAccess"] === "project";
|
|
13518
|
+
const toolsCfg = decrypted.tools ?? {};
|
|
13519
|
+
toolsCfg.restrictToProjectRoot = restrict;
|
|
13520
|
+
decrypted.tools = toolsCfg;
|
|
13521
|
+
const featsCfg = decrypted.features ?? {};
|
|
13522
|
+
featsCfg.allowOutsideProjectRoot = !restrict;
|
|
13523
|
+
decrypted.features = featsCfg;
|
|
13524
|
+
}
|
|
13525
|
+
if (typeof payload["debugStream"] === "boolean")
|
|
13526
|
+
decrypted.debugStream = payload["debugStream"];
|
|
13527
|
+
if (typeof payload["pluginsEnabled"] === "object" && payload["pluginsEnabled"] !== null) {
|
|
13528
|
+
const ext = decrypted.extensions ?? {};
|
|
13529
|
+
for (const [pluginName, enabled] of Object.entries(
|
|
13530
|
+
payload["pluginsEnabled"]
|
|
13531
|
+
)) {
|
|
13532
|
+
if (FORBIDDEN_PROTO_KEYS2.has(pluginName)) continue;
|
|
13533
|
+
const pExt = ext[pluginName] ?? {};
|
|
13534
|
+
pExt["enabled"] = enabled;
|
|
13535
|
+
ext[pluginName] = pExt;
|
|
13536
|
+
}
|
|
13537
|
+
decrypted.extensions = ext;
|
|
13538
|
+
}
|
|
13539
|
+
const chimeraTouched = typeof payload["chimeraEnabled"] === "boolean" || typeof payload["chimeraProvider"] === "string" || typeof payload["chimeraModel"] === "string" || typeof payload["chimeraMaxFiles"] === "number" || typeof payload["chimeraAutoFix"] === "string";
|
|
13540
|
+
if (chimeraTouched) {
|
|
13541
|
+
const ext = decrypted.extensions ?? {};
|
|
13542
|
+
const chimera = ext["wstack-chimera"] ?? {};
|
|
13543
|
+
if (typeof payload["chimeraEnabled"] === "boolean")
|
|
13544
|
+
chimera["enabled"] = payload["chimeraEnabled"];
|
|
13545
|
+
if (typeof payload["chimeraProvider"] === "string")
|
|
13546
|
+
chimera["provider"] = payload["chimeraProvider"];
|
|
13547
|
+
if (typeof payload["chimeraModel"] === "string") chimera["model"] = payload["chimeraModel"];
|
|
13548
|
+
if (typeof payload["chimeraMaxFiles"] === "number" && payload["chimeraMaxFiles"] >= 1) {
|
|
13549
|
+
chimera["maxFiles"] = payload["chimeraMaxFiles"];
|
|
13550
|
+
}
|
|
13551
|
+
if (typeof payload["chimeraAutoFix"] === "string") {
|
|
13552
|
+
if (payload["chimeraAutoFix"] === "off" || payload["chimeraAutoFix"] === "ask" || payload["chimeraAutoFix"] === "auto") {
|
|
13553
|
+
chimera["autoFix"] = payload["chimeraAutoFix"];
|
|
13554
|
+
}
|
|
13555
|
+
}
|
|
13556
|
+
ext["wstack-chimera"] = chimera;
|
|
13557
|
+
decrypted.extensions = ext;
|
|
13558
|
+
}
|
|
13559
|
+
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";
|
|
13560
|
+
if (autoReviewTouched) {
|
|
13561
|
+
const ext = decrypted.extensions ?? {};
|
|
13562
|
+
const ar = ext["wstack-auto-review"] ?? {};
|
|
13563
|
+
if (typeof payload["autoReviewEnabled"] === "boolean")
|
|
13564
|
+
ar["enabled"] = payload["autoReviewEnabled"];
|
|
13565
|
+
if (typeof payload["autoReviewProvider"] === "string")
|
|
13566
|
+
ar["provider"] = payload["autoReviewProvider"];
|
|
13567
|
+
if (typeof payload["autoReviewModel"] === "string")
|
|
13568
|
+
ar["model"] = payload["autoReviewModel"];
|
|
13569
|
+
if (typeof payload["autoReviewFallbackProfile"] === "string") {
|
|
13570
|
+
if (payload["autoReviewFallbackProfile"] === "") {
|
|
13571
|
+
delete ar["fallbackProfile"];
|
|
13572
|
+
} else {
|
|
13573
|
+
ar["fallbackProfile"] = payload["autoReviewFallbackProfile"];
|
|
13574
|
+
}
|
|
13575
|
+
}
|
|
13576
|
+
if (typeof payload["autoReviewDebounceMs"] === "number" && payload["autoReviewDebounceMs"] >= 0) {
|
|
13577
|
+
ar["debounceMs"] = payload["autoReviewDebounceMs"];
|
|
13578
|
+
}
|
|
13579
|
+
if (typeof payload["autoReviewMaxFilesPerBatch"] === "number" && payload["autoReviewMaxFilesPerBatch"] >= 1) {
|
|
13580
|
+
ar["maxFilesPerBatch"] = payload["autoReviewMaxFilesPerBatch"];
|
|
13581
|
+
}
|
|
13582
|
+
if (typeof payload["autoReviewMaxConcurrentReviews"] === "number" && payload["autoReviewMaxConcurrentReviews"] >= 1) {
|
|
13583
|
+
ar["maxConcurrentReviews"] = payload["autoReviewMaxConcurrentReviews"];
|
|
13584
|
+
}
|
|
13585
|
+
if (typeof payload["autoReviewCascadeOn"] === "string") {
|
|
13586
|
+
if (payload["autoReviewCascadeOn"] === "off" || payload["autoReviewCascadeOn"] === "critical" || payload["autoReviewCascadeOn"] === "high") {
|
|
13587
|
+
ar["cascadeOn"] = payload["autoReviewCascadeOn"];
|
|
13588
|
+
}
|
|
13420
13589
|
}
|
|
13590
|
+
ext["wstack-auto-review"] = ar;
|
|
13591
|
+
decrypted.extensions = ext;
|
|
13421
13592
|
}
|
|
13422
|
-
|
|
13423
|
-
|
|
13424
|
-
|
|
13425
|
-
}, "prefs");
|
|
13593
|
+
},
|
|
13594
|
+
"prefs"
|
|
13595
|
+
);
|
|
13426
13596
|
}
|
|
13427
13597
|
|
|
13428
13598
|
// src/server/provider-handlers.ts
|
|
@@ -13472,13 +13642,13 @@ async function probeModelDescriptors(cfg) {
|
|
|
13472
13642
|
}
|
|
13473
13643
|
}
|
|
13474
13644
|
function createProviderHandlers(deps2) {
|
|
13475
|
-
const { globalConfigPath, vault, broadcast: broadcast2, clients } = deps2;
|
|
13645
|
+
const { globalConfigPath, profileConfigPath, vault, broadcast: broadcast2, clients } = deps2;
|
|
13476
13646
|
let configWriteLock = deps2.getConfigWriteLock();
|
|
13477
13647
|
async function loadConfigProviders() {
|
|
13478
13648
|
return loadSavedProviders(globalConfigPath, vault);
|
|
13479
13649
|
}
|
|
13480
13650
|
async function saveConfigProviders(providers) {
|
|
13481
|
-
const next = configWriteLock.then(() => saveProviders(globalConfigPath, vault, providers)).catch((err) => {
|
|
13651
|
+
const next = configWriteLock.then(() => saveProviders(globalConfigPath, vault, providers, profileConfigPath)).catch((err) => {
|
|
13482
13652
|
const msg = toErrorMessage9(err);
|
|
13483
13653
|
console.error(JSON.stringify({
|
|
13484
13654
|
level: "error",
|
|
@@ -13753,13 +13923,14 @@ function createProviderHandlers(deps2) {
|
|
|
13753
13923
|
}
|
|
13754
13924
|
|
|
13755
13925
|
// src/server/routes.ts
|
|
13756
|
-
import
|
|
13926
|
+
import path23 from "node:path";
|
|
13757
13927
|
import {
|
|
13758
13928
|
buildRefinerContextSections,
|
|
13759
13929
|
enhanceUserPrompt,
|
|
13760
13930
|
gatedEnhancerReasoning,
|
|
13761
13931
|
nextEnhanceTimeout,
|
|
13762
13932
|
recentTextTurns,
|
|
13933
|
+
resolveConfiguredRefinerRef,
|
|
13763
13934
|
resolveEnhanceFallbackRef,
|
|
13764
13935
|
resolveProviderModelList
|
|
13765
13936
|
} from "@wrongstack/core";
|
|
@@ -13963,7 +14134,7 @@ function createModeHandlers(ctx) {
|
|
|
13963
14134
|
}
|
|
13964
14135
|
|
|
13965
14136
|
// src/server/project-handlers.ts
|
|
13966
|
-
import * as
|
|
14137
|
+
import * as path22 from "node:path";
|
|
13967
14138
|
function createProjectHandlers(ctx) {
|
|
13968
14139
|
return {
|
|
13969
14140
|
listProjects: async (ws) => {
|
|
@@ -13989,7 +14160,7 @@ function createProjectHandlers(ctx) {
|
|
|
13989
14160
|
selectProject: async (ws, msg) => {
|
|
13990
14161
|
const payload = msg.payload;
|
|
13991
14162
|
const root = typeof payload?.root === "string" ? payload.root : "";
|
|
13992
|
-
const name2 = typeof payload?.name === "string" ? payload.name : root ?
|
|
14163
|
+
const name2 = typeof payload?.name === "string" ? payload.name : root ? path22.basename(root) : "";
|
|
13993
14164
|
send(ws, {
|
|
13994
14165
|
type: "projects.selected",
|
|
13995
14166
|
payload: {
|
|
@@ -14443,7 +14614,9 @@ async function enrichProviderModelDescriptors(modelsRegistry, providerId, cfg, m
|
|
|
14443
14614
|
if (resolved.capabilities.vision) capabilities.add("vision");
|
|
14444
14615
|
return {
|
|
14445
14616
|
...model,
|
|
14446
|
-
contextWindow: model.contextWindow
|
|
14617
|
+
contextWindow: model.contextWindow ?? resolved.capabilities.maxContext ?? void 0,
|
|
14618
|
+
inputCost: model.inputCost ?? resolved.cost?.input,
|
|
14619
|
+
outputCost: model.outputCost ?? resolved.cost?.output,
|
|
14447
14620
|
capabilities: [...capabilities]
|
|
14448
14621
|
};
|
|
14449
14622
|
})
|
|
@@ -14452,6 +14625,7 @@ async function enrichProviderModelDescriptors(modelsRegistry, providerId, cfg, m
|
|
|
14452
14625
|
function buildRoutes(state, deps2, cb) {
|
|
14453
14626
|
const providerHandlers = createProviderHandlers({
|
|
14454
14627
|
globalConfigPath: deps2.globalConfigPath,
|
|
14628
|
+
profileConfigPath: deps2.profileConfigPath,
|
|
14455
14629
|
vault: deps2.vault,
|
|
14456
14630
|
getConfigWriteLock: state.getConfigWriteLock,
|
|
14457
14631
|
setConfigWriteLock: state.setConfigWriteLock,
|
|
@@ -14622,6 +14796,26 @@ function buildRoutes(state, deps2, cb) {
|
|
|
14622
14796
|
});
|
|
14623
14797
|
return;
|
|
14624
14798
|
}
|
|
14799
|
+
} else {
|
|
14800
|
+
const configuredRef = resolveConfiguredRefinerRef({
|
|
14801
|
+
...cfg,
|
|
14802
|
+
provider: providerId,
|
|
14803
|
+
model
|
|
14804
|
+
});
|
|
14805
|
+
if (configuredRef) {
|
|
14806
|
+
const slash = configuredRef.indexOf("/");
|
|
14807
|
+
const configuredProvider = slash > 0 ? configuredRef.slice(0, slash) : providerId;
|
|
14808
|
+
const configuredModel = slash > 0 ? configuredRef.slice(slash + 1) : configuredRef;
|
|
14809
|
+
try {
|
|
14810
|
+
const providerCfg = cfg.providers?.[configuredProvider] ?? {
|
|
14811
|
+
type: configuredProvider
|
|
14812
|
+
};
|
|
14813
|
+
provider = deps2.providerRegistry.has(configuredProvider) ? deps2.providerRegistry.create({ ...providerCfg, type: configuredProvider }) : makeProviderFromConfig2(configuredProvider, providerCfg);
|
|
14814
|
+
providerId = configuredProvider;
|
|
14815
|
+
model = configuredModel;
|
|
14816
|
+
} catch {
|
|
14817
|
+
}
|
|
14818
|
+
}
|
|
14625
14819
|
}
|
|
14626
14820
|
const baseTimeout = 9e4;
|
|
14627
14821
|
const timeoutMs = typeof payload.timeoutMs === "number" && payload.timeoutMs > 0 ? payload.timeoutMs : baseTimeout;
|
|
@@ -14808,19 +15002,27 @@ function buildRoutes(state, deps2, cb) {
|
|
|
14808
15002
|
cfg.favoriteModels = payload["favoriteModels"];
|
|
14809
15003
|
if (typeof payload["favoriteModelsOnly"] === "boolean")
|
|
14810
15004
|
cfg.favoriteModelsOnly = payload["favoriteModelsOnly"];
|
|
15005
|
+
if (Array.isArray(payload["modelAvailabilitySchedule"]))
|
|
15006
|
+
cfg.modelAvailabilitySchedule = payload["modelAvailabilitySchedule"];
|
|
14811
15007
|
if (payload["modelMatrix"] && typeof payload["modelMatrix"] === "object" && !Array.isArray(payload["modelMatrix"])) {
|
|
14812
15008
|
cfg.modelMatrix = payload["modelMatrix"];
|
|
14813
15009
|
}
|
|
14814
15010
|
if (typeof payload["fallbackAuto"] === "boolean") cfg.fallbackAuto = payload["fallbackAuto"];
|
|
14815
15011
|
const routingPatch = {};
|
|
14816
|
-
if (Array.isArray(payload["fallbackModels"]))
|
|
15012
|
+
if (Array.isArray(payload["fallbackModels"]))
|
|
15013
|
+
routingPatch.fallbackModels = payload["fallbackModels"];
|
|
14817
15014
|
if (payload["fallbackProfiles"] && typeof payload["fallbackProfiles"] === "object" && !Array.isArray(payload["fallbackProfiles"]))
|
|
14818
15015
|
routingPatch.fallbackProfiles = payload["fallbackProfiles"];
|
|
14819
|
-
if (Array.isArray(payload["favoriteModels"]))
|
|
14820
|
-
|
|
15016
|
+
if (Array.isArray(payload["favoriteModels"]))
|
|
15017
|
+
routingPatch.favoriteModels = payload["favoriteModels"];
|
|
15018
|
+
if (typeof payload["favoriteModelsOnly"] === "boolean")
|
|
15019
|
+
routingPatch.favoriteModelsOnly = payload["favoriteModelsOnly"];
|
|
15020
|
+
if (Array.isArray(payload["modelAvailabilitySchedule"]))
|
|
15021
|
+
routingPatch.modelAvailabilitySchedule = payload["modelAvailabilitySchedule"];
|
|
14821
15022
|
if (payload["modelMatrix"] && typeof payload["modelMatrix"] === "object" && !Array.isArray(payload["modelMatrix"]))
|
|
14822
15023
|
routingPatch.modelMatrix = payload["modelMatrix"];
|
|
14823
|
-
if (typeof payload["fallbackAuto"] === "boolean")
|
|
15024
|
+
if (typeof payload["fallbackAuto"] === "boolean")
|
|
15025
|
+
routingPatch.fallbackAuto = payload["fallbackAuto"];
|
|
14824
15026
|
if (Object.keys(routingPatch).length > 0)
|
|
14825
15027
|
deps2.configStore.update(routingPatch);
|
|
14826
15028
|
if (typeof payload["contextAutoCompact"] === "boolean") {
|
|
@@ -14891,7 +15093,7 @@ function buildRoutes(state, deps2, cb) {
|
|
|
14891
15093
|
}
|
|
14892
15094
|
return handleMailboxMessages(
|
|
14893
15095
|
ws,
|
|
14894
|
-
{ projectRoot: state.getProjectRoot(), globalRoot:
|
|
15096
|
+
{ projectRoot: state.getProjectRoot(), globalRoot: path23.dirname(deps2.globalConfigPath) },
|
|
14895
15097
|
parsed.value
|
|
14896
15098
|
);
|
|
14897
15099
|
},
|
|
@@ -14903,13 +15105,13 @@ function buildRoutes(state, deps2, cb) {
|
|
|
14903
15105
|
}
|
|
14904
15106
|
return handleMailboxAgents(
|
|
14905
15107
|
ws,
|
|
14906
|
-
{ projectRoot: state.getProjectRoot(), globalRoot:
|
|
15108
|
+
{ projectRoot: state.getProjectRoot(), globalRoot: path23.dirname(deps2.globalConfigPath) },
|
|
14907
15109
|
parsed.value
|
|
14908
15110
|
);
|
|
14909
15111
|
},
|
|
14910
15112
|
clear: (ws) => handleMailboxClear(ws, {
|
|
14911
15113
|
projectRoot: state.getProjectRoot(),
|
|
14912
|
-
globalRoot:
|
|
15114
|
+
globalRoot: path23.dirname(deps2.globalConfigPath)
|
|
14913
15115
|
}),
|
|
14914
15116
|
purge: (ws, msg) => {
|
|
14915
15117
|
const parsed = validateMailboxPurgePayload(msg.payload);
|
|
@@ -14919,14 +15121,14 @@ function buildRoutes(state, deps2, cb) {
|
|
|
14919
15121
|
}
|
|
14920
15122
|
return handleMailboxPurge(
|
|
14921
15123
|
ws,
|
|
14922
|
-
{ projectRoot: state.getProjectRoot(), globalRoot:
|
|
15124
|
+
{ projectRoot: state.getProjectRoot(), globalRoot: path23.dirname(deps2.globalConfigPath) },
|
|
14923
15125
|
parsed.value
|
|
14924
15126
|
);
|
|
14925
15127
|
},
|
|
14926
15128
|
compact: (ws, msg) => {
|
|
14927
15129
|
return handleMailboxCompact(
|
|
14928
15130
|
ws,
|
|
14929
|
-
{ projectRoot: state.getProjectRoot(), globalRoot:
|
|
15131
|
+
{ projectRoot: state.getProjectRoot(), globalRoot: path23.dirname(deps2.globalConfigPath) },
|
|
14930
15132
|
msg.payload ?? {}
|
|
14931
15133
|
);
|
|
14932
15134
|
}
|
|
@@ -15077,7 +15279,9 @@ async function startWebUI(opts = {}) {
|
|
|
15077
15279
|
let projectRoot = boot.projectRoot;
|
|
15078
15280
|
let workingDir = projectRoot;
|
|
15079
15281
|
const configWriteLock = { lock: Promise.resolve() };
|
|
15080
|
-
const
|
|
15282
|
+
const activeProfile = config.activeProfile ?? "default";
|
|
15283
|
+
const profileConfigPath = wpaths.profileConfig(activeProfile);
|
|
15284
|
+
const prefHelperDeps = { globalConfigPath, profileConfigPath, vault, logger };
|
|
15081
15285
|
const updateGlobalConfig2 = async (mutate, errorLabel) => updateGlobalConfig(prefHelperDeps, configWriteLock, mutate, errorLabel);
|
|
15082
15286
|
console.log("[WebUI] Config loaded:", config.provider ?? "(none)", "/", config.model ?? "(none)");
|
|
15083
15287
|
if (!config.provider && config.providers && typeof config.providers === "object" && config.providers !== null && !Array.isArray(config.providers) && Object.keys(config.providers).length > 0) {
|
|
@@ -15239,21 +15443,21 @@ async function startWebUI(opts = {}) {
|
|
|
15239
15443
|
wpaths
|
|
15240
15444
|
}, watcherMetricsRef);
|
|
15241
15445
|
async function touchProjectEntry(root, workDir) {
|
|
15242
|
-
const resolved =
|
|
15446
|
+
const resolved = path24.resolve(root);
|
|
15243
15447
|
const manifest = await loadManifest(globalConfigPath);
|
|
15244
15448
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
15245
|
-
const existing = manifest.projects.find((p) =>
|
|
15449
|
+
const existing = manifest.projects.find((p) => path24.resolve(p.root) === resolved);
|
|
15246
15450
|
if (existing) {
|
|
15247
15451
|
existing.lastSeen = now;
|
|
15248
|
-
if (workDir) existing.lastWorkingDir =
|
|
15452
|
+
if (workDir) existing.lastWorkingDir = path24.resolve(workDir);
|
|
15249
15453
|
} else {
|
|
15250
15454
|
manifest.projects.push({
|
|
15251
|
-
name:
|
|
15455
|
+
name: path24.basename(resolved),
|
|
15252
15456
|
root: resolved,
|
|
15253
15457
|
slug: generateProjectSlug(resolved),
|
|
15254
15458
|
createdAt: now,
|
|
15255
15459
|
lastSeen: now,
|
|
15256
|
-
lastWorkingDir: workDir ?
|
|
15460
|
+
lastWorkingDir: workDir ? path24.resolve(workDir) : void 0
|
|
15257
15461
|
});
|
|
15258
15462
|
}
|
|
15259
15463
|
await saveManifest(manifest, globalConfigPath);
|
|
@@ -15360,6 +15564,7 @@ async function startWebUI(opts = {}) {
|
|
|
15360
15564
|
persistPrefsToConfig: persistPrefsToConfig2,
|
|
15361
15565
|
prefSnapshot: prefSnapshot2
|
|
15362
15566
|
};
|
|
15567
|
+
const watchConfigPath = profileConfigPath ?? globalConfigPath;
|
|
15363
15568
|
let credentialWatcherClose;
|
|
15364
15569
|
if (process.env["WRONGSTACK_DISABLE_CONFIG_WATCH"] !== "1") {
|
|
15365
15570
|
let lastActiveCfg = JSON.stringify(
|
|
@@ -15367,7 +15572,7 @@ async function startWebUI(opts = {}) {
|
|
|
15367
15572
|
);
|
|
15368
15573
|
let lastUiLocale = state.getConfig().uiLocale;
|
|
15369
15574
|
const credentialWatcher = watchProviderConfig(
|
|
15370
|
-
|
|
15575
|
+
watchConfigPath,
|
|
15371
15576
|
vault,
|
|
15372
15577
|
(snapshot) => {
|
|
15373
15578
|
state.setConfig(
|
|
@@ -15508,7 +15713,7 @@ async function startWebUI(opts = {}) {
|
|
|
15508
15713
|
archiveLowConfidenceAfterDays: config.superMemory?.hygiene?.archiveLowConfidenceAfterDays
|
|
15509
15714
|
}).catch((err) => logger.warn(`super-memory session hygiene failed: ${toErrorMessage10(err)}`));
|
|
15510
15715
|
}
|
|
15511
|
-
await unregisterInstance(process.pid,
|
|
15716
|
+
await unregisterInstance(process.pid, path24.dirname(globalConfigPath));
|
|
15512
15717
|
}
|
|
15513
15718
|
});
|
|
15514
15719
|
}
|
|
@@ -15719,6 +15924,7 @@ export {
|
|
|
15719
15924
|
handleSuperMemoryForFile,
|
|
15720
15925
|
handleSuperMemoryGet,
|
|
15721
15926
|
handleSuperMemoryList,
|
|
15927
|
+
handleSuperMemoryListPage,
|
|
15722
15928
|
handleSuperMemoryRecover,
|
|
15723
15929
|
handleSuperMemoryRemember,
|
|
15724
15930
|
handleSuperMemoryUpdate,
|
|
@@ -15744,6 +15950,7 @@ export {
|
|
|
15744
15950
|
normalizeCodeMapFileTarget,
|
|
15745
15951
|
normalizeKeys,
|
|
15746
15952
|
openBrowser,
|
|
15953
|
+
paginateKanbanBoards,
|
|
15747
15954
|
patchConfig,
|
|
15748
15955
|
persistPrefsToConfig,
|
|
15749
15956
|
projectSavedProviders,
|