@wrongstack/webui-server 0.298.0 → 0.298.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 +96 -74
- package/dist/protocol/index.js +1 -0
- package/dist/protocol/registry.d.ts +1 -1
- package/dist/protocol/server-conversation.d.ts +1 -1
- package/dist/server/entry.js +96 -74
- package/dist/server/http-server.d.ts +3 -1
- package/package.json +11 -11
package/dist/index.js
CHANGED
|
@@ -73,8 +73,7 @@ var BOOLEAN_PREF_KEYS = /* @__PURE__ */ new Set([
|
|
|
73
73
|
// Display-only toggles (purely visual, persisted in localStorage via Zustand).
|
|
74
74
|
"groupToolCalls",
|
|
75
75
|
"showThinkingLogs",
|
|
76
|
-
// v11 Display parity:
|
|
77
|
-
"showAgentSwarmPanel",
|
|
76
|
+
// v11 Display parity: inverse fsAccess flag.
|
|
78
77
|
"allowOutsideProjectRoot",
|
|
79
78
|
// v13 Display parity (TUI SettingsPicker fields 42 & 43): the read tool
|
|
80
79
|
// includes codebase-index symbols, and SAGE memory-inject blocks are
|
|
@@ -169,7 +168,8 @@ var ENUM_PREF_KEYS = {
|
|
|
169
168
|
// Chimera autoFix + auto-review cascade threshold
|
|
170
169
|
chimeraAutoFix: /* @__PURE__ */ new Set(["off", "ask", "auto"]),
|
|
171
170
|
autoReviewCascadeOn: /* @__PURE__ */ new Set(["off", "critical", "high"]),
|
|
172
|
-
fleetChatVerbosity: /* @__PURE__ */ new Set(["off", "full"])
|
|
171
|
+
fleetChatVerbosity: /* @__PURE__ */ new Set(["off", "full"]),
|
|
172
|
+
showAgentSwarmPanel: /* @__PURE__ */ new Set(["bottom", "sidebar", "off"])
|
|
173
173
|
};
|
|
174
174
|
function validateModelRuntimeValue(modelRuntime, path35) {
|
|
175
175
|
const reasoning = modelRuntime["reasoning"];
|
|
@@ -8978,7 +8978,7 @@ function buildCspHeader(publicWsUrl, host, port) {
|
|
|
8978
8978
|
if (host && isLoopbackHostname(host)) {
|
|
8979
8979
|
const p = port ?? 3456;
|
|
8980
8980
|
if (p > 0 && p <= 65535) {
|
|
8981
|
-
for (const h of ["127.0.0.1", "localhost"
|
|
8981
|
+
for (const h of ["127.0.0.1", "localhost"]) {
|
|
8982
8982
|
connect.add(`ws://${h}:${p}`);
|
|
8983
8983
|
connect.add(`wss://${h}:${p}`);
|
|
8984
8984
|
}
|
|
@@ -16365,6 +16365,7 @@ var SERVER_CONVERSATION_MESSAGE_TYPES = [
|
|
|
16365
16365
|
"agent.status_changed",
|
|
16366
16366
|
"agent.timeline.message",
|
|
16367
16367
|
"client.status_update",
|
|
16368
|
+
"chimera.report_available",
|
|
16368
16369
|
"compaction.failed",
|
|
16369
16370
|
"completion.result",
|
|
16370
16371
|
"context.compacted",
|
|
@@ -20053,12 +20054,67 @@ var SddWizardWebSocketHandler = class {
|
|
|
20053
20054
|
// src/server/setup-events.ts
|
|
20054
20055
|
import { recordTaskFileActivity } from "@wrongstack/kanban";
|
|
20055
20056
|
|
|
20057
|
+
// src/server/setup-events-core-watchers.ts
|
|
20058
|
+
import * as fs19 from "node:fs/promises";
|
|
20059
|
+
import * as path24 from "node:path";
|
|
20060
|
+
function registerSetupEventsCoreWatchers(deps2) {
|
|
20061
|
+
const { broadcast: broadcast2, clients, context } = deps2;
|
|
20062
|
+
const disposers = [];
|
|
20063
|
+
const conversationState = context.state;
|
|
20064
|
+
if (typeof conversationState?.onChange === "function") {
|
|
20065
|
+
disposers.push(
|
|
20066
|
+
conversationState.onChange((change) => {
|
|
20067
|
+
if (change.kind !== "todos_replaced") return;
|
|
20068
|
+
broadcast2(clients, {
|
|
20069
|
+
type: "todos.updated",
|
|
20070
|
+
payload: {
|
|
20071
|
+
sessionId: context.session?.id ?? "",
|
|
20072
|
+
todos: [...change.todos],
|
|
20073
|
+
revision: conversationState.revision
|
|
20074
|
+
}
|
|
20075
|
+
});
|
|
20076
|
+
})
|
|
20077
|
+
);
|
|
20078
|
+
}
|
|
20079
|
+
const projectRoot = context.projectRoot;
|
|
20080
|
+
if (projectRoot) {
|
|
20081
|
+
disposers.push(
|
|
20082
|
+
subscribeKanbanDaemonEvents(projectRoot, (message) => broadcast2(clients, message))
|
|
20083
|
+
);
|
|
20084
|
+
}
|
|
20085
|
+
return disposers;
|
|
20086
|
+
}
|
|
20087
|
+
function registerSetupEventsClientStatusWriter(deps2) {
|
|
20088
|
+
const { broadcast: broadcast2, clients, events, wpaths } = deps2;
|
|
20089
|
+
const on = (event, listener) => events.on(event, listener);
|
|
20090
|
+
return on("client.status", async (e) => {
|
|
20091
|
+
broadcast2(clients, { type: "client.status_update", payload: e });
|
|
20092
|
+
if (wpaths?.projectStatus) {
|
|
20093
|
+
try {
|
|
20094
|
+
const statusFile = wpaths.projectStatus(e.projectHash);
|
|
20095
|
+
const dir = path24.dirname(statusFile);
|
|
20096
|
+
await fs19.mkdir(dir, { recursive: true });
|
|
20097
|
+
await fs19.writeFile(statusFile, JSON.stringify(e, null, 2), "utf-8");
|
|
20098
|
+
} catch (err) {
|
|
20099
|
+
console.error(
|
|
20100
|
+
JSON.stringify({
|
|
20101
|
+
level: "error",
|
|
20102
|
+
event: "setup_events.status_write_failed",
|
|
20103
|
+
message: err instanceof Error ? err.message : String(err),
|
|
20104
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
20105
|
+
})
|
|
20106
|
+
);
|
|
20107
|
+
}
|
|
20108
|
+
}
|
|
20109
|
+
});
|
|
20110
|
+
}
|
|
20111
|
+
|
|
20056
20112
|
// src/server/setup-events-fleet-broadcaster.ts
|
|
20057
20113
|
import { watch as fsWatch } from "node:fs";
|
|
20058
|
-
import * as
|
|
20114
|
+
import * as path25 from "node:path";
|
|
20059
20115
|
function registerSetupEventsFleetBroadcaster(deps2) {
|
|
20060
20116
|
const { globalConfigPath, wpaths, context, clients, broadcast: broadcast2, onFleetBroadcaster, isDisposed } = deps2;
|
|
20061
|
-
const globalRoot = globalConfigPath ?
|
|
20117
|
+
const globalRoot = globalConfigPath ? path25.dirname(globalConfigPath) : void 0;
|
|
20062
20118
|
if (!globalRoot) return void 0;
|
|
20063
20119
|
const disposers = [];
|
|
20064
20120
|
const broadcastSessions = async () => {
|
|
@@ -20068,8 +20124,8 @@ function registerSetupEventsFleetBroadcaster(deps2) {
|
|
|
20068
20124
|
const sessions = await registry.list();
|
|
20069
20125
|
const ownEntry = sessions.find((s) => s.pid === process.pid);
|
|
20070
20126
|
const mySlug = ownEntry?.projectSlug ?? wpaths?.projectSlug;
|
|
20071
|
-
const myRoot =
|
|
20072
|
-
const live = sessions.filter((s) => s.status === "active" || s.status === "idle").filter((s) => mySlug ? s.projectSlug === mySlug :
|
|
20127
|
+
const myRoot = path25.resolve(context.projectRoot);
|
|
20128
|
+
const live = sessions.filter((s) => s.status === "active" || s.status === "idle").filter((s) => mySlug ? s.projectSlug === mySlug : path25.resolve(s.projectRoot) === myRoot).map((s) => ({
|
|
20073
20129
|
sessionId: s.sessionId,
|
|
20074
20130
|
projectName: s.projectName,
|
|
20075
20131
|
projectSlug: s.projectSlug,
|
|
@@ -20259,14 +20315,14 @@ function createSetupEventSessionHelpers(context, sessionBridge) {
|
|
|
20259
20315
|
|
|
20260
20316
|
// src/server/setup-events-status-watcher.ts
|
|
20261
20317
|
import { watch as fsWatch2 } from "node:fs";
|
|
20262
|
-
import * as
|
|
20263
|
-
import * as
|
|
20318
|
+
import * as fs20 from "node:fs/promises";
|
|
20319
|
+
import * as path27 from "node:path";
|
|
20264
20320
|
|
|
20265
20321
|
// src/server/setup-events-watcher.ts
|
|
20266
|
-
import * as
|
|
20322
|
+
import * as path26 from "node:path";
|
|
20267
20323
|
function statusProjectHashFromWatchFilename(projectsDir, filename) {
|
|
20268
20324
|
const raw = String(filename);
|
|
20269
|
-
const relative5 =
|
|
20325
|
+
const relative5 = path26.isAbsolute(raw) ? path26.relative(projectsDir, raw) : raw;
|
|
20270
20326
|
const parts = relative5.split(/[\\/]+/).filter(Boolean);
|
|
20271
20327
|
if (parts.length < 2 || parts.at(-1) !== "status.json") return null;
|
|
20272
20328
|
return parts.at(-2) ?? null;
|
|
@@ -20301,7 +20357,7 @@ function logFileWatcherMetrics(metrics) {
|
|
|
20301
20357
|
function registerSetupEventsStatusWatcher(deps2) {
|
|
20302
20358
|
const { wpaths, watcherMetrics, clients, broadcast: broadcast2, on, isDisposed } = deps2;
|
|
20303
20359
|
if (!wpaths?.projectStatus || !wpaths.globalRoot) return void 0;
|
|
20304
|
-
const projectsDir =
|
|
20360
|
+
const projectsDir = path27.join(wpaths.globalRoot, "projects");
|
|
20305
20361
|
const knownProjectHashes = /* @__PURE__ */ new Set();
|
|
20306
20362
|
const debounceTimers = /* @__PURE__ */ new Map();
|
|
20307
20363
|
const DEBOUNCE_MS2 = 150;
|
|
@@ -20346,7 +20402,7 @@ function registerSetupEventsStatusWatcher(deps2) {
|
|
|
20346
20402
|
let watcher;
|
|
20347
20403
|
const startWatcher = async () => {
|
|
20348
20404
|
try {
|
|
20349
|
-
await
|
|
20405
|
+
await fs20.mkdir(projectsDir, { recursive: true });
|
|
20350
20406
|
if (isDisposed()) return;
|
|
20351
20407
|
watcher = fsWatch2(
|
|
20352
20408
|
projectsDir,
|
|
@@ -20360,8 +20416,8 @@ function registerSetupEventsStatusWatcher(deps2) {
|
|
|
20360
20416
|
if (!knownProjectHashes.has(projectHash)) return;
|
|
20361
20417
|
if (watcherMetrics) watcherMetrics.filesProcessed++;
|
|
20362
20418
|
try {
|
|
20363
|
-
const targetFile =
|
|
20364
|
-
const content = await
|
|
20419
|
+
const targetFile = path27.join(projectsDir, projectHash, "status.json");
|
|
20420
|
+
const content = await fs20.readFile(targetFile, "utf-8");
|
|
20365
20421
|
const statusData = JSON.parse(content);
|
|
20366
20422
|
scheduleBroadcast(projectHash, statusData);
|
|
20367
20423
|
} catch {
|
|
@@ -20417,61 +20473,6 @@ function registerSetupEventsStatusWatcher(deps2) {
|
|
|
20417
20473
|
};
|
|
20418
20474
|
}
|
|
20419
20475
|
|
|
20420
|
-
// src/server/setup-events-core-watchers.ts
|
|
20421
|
-
import * as fs20 from "node:fs/promises";
|
|
20422
|
-
import * as path27 from "node:path";
|
|
20423
|
-
function registerSetupEventsCoreWatchers(deps2) {
|
|
20424
|
-
const { broadcast: broadcast2, clients, context } = deps2;
|
|
20425
|
-
const disposers = [];
|
|
20426
|
-
const conversationState = context.state;
|
|
20427
|
-
if (typeof conversationState?.onChange === "function") {
|
|
20428
|
-
disposers.push(
|
|
20429
|
-
conversationState.onChange((change) => {
|
|
20430
|
-
if (change.kind !== "todos_replaced") return;
|
|
20431
|
-
broadcast2(clients, {
|
|
20432
|
-
type: "todos.updated",
|
|
20433
|
-
payload: {
|
|
20434
|
-
sessionId: context.session?.id ?? "",
|
|
20435
|
-
todos: [...change.todos],
|
|
20436
|
-
revision: conversationState.revision
|
|
20437
|
-
}
|
|
20438
|
-
});
|
|
20439
|
-
})
|
|
20440
|
-
);
|
|
20441
|
-
}
|
|
20442
|
-
const projectRoot = context.projectRoot;
|
|
20443
|
-
if (projectRoot) {
|
|
20444
|
-
disposers.push(
|
|
20445
|
-
subscribeKanbanDaemonEvents(projectRoot, (message) => broadcast2(clients, message))
|
|
20446
|
-
);
|
|
20447
|
-
}
|
|
20448
|
-
return disposers;
|
|
20449
|
-
}
|
|
20450
|
-
function registerSetupEventsClientStatusWriter(deps2) {
|
|
20451
|
-
const { broadcast: broadcast2, clients, events, wpaths } = deps2;
|
|
20452
|
-
const on = (event, listener) => events.on(event, listener);
|
|
20453
|
-
return on("client.status", async (e) => {
|
|
20454
|
-
broadcast2(clients, { type: "client.status_update", payload: e });
|
|
20455
|
-
if (wpaths?.projectStatus) {
|
|
20456
|
-
try {
|
|
20457
|
-
const statusFile = wpaths.projectStatus(e.projectHash);
|
|
20458
|
-
const dir = path27.dirname(statusFile);
|
|
20459
|
-
await fs20.mkdir(dir, { recursive: true });
|
|
20460
|
-
await fs20.writeFile(statusFile, JSON.stringify(e, null, 2), "utf-8");
|
|
20461
|
-
} catch (err) {
|
|
20462
|
-
console.error(
|
|
20463
|
-
JSON.stringify({
|
|
20464
|
-
level: "error",
|
|
20465
|
-
event: "setup_events.status_write_failed",
|
|
20466
|
-
message: err instanceof Error ? err.message : String(err),
|
|
20467
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
20468
|
-
})
|
|
20469
|
-
);
|
|
20470
|
-
}
|
|
20471
|
-
}
|
|
20472
|
-
});
|
|
20473
|
-
}
|
|
20474
|
-
|
|
20475
20476
|
// src/server/setup-events.ts
|
|
20476
20477
|
function setupEvents(deps2) {
|
|
20477
20478
|
const {
|
|
@@ -21027,6 +21028,12 @@ function setupEvents(deps2) {
|
|
|
21027
21028
|
});
|
|
21028
21029
|
});
|
|
21029
21030
|
disposers.push(
|
|
21031
|
+
events.onPattern("chimera.report_available", (_event, payload) => {
|
|
21032
|
+
broadcast2(clients, {
|
|
21033
|
+
type: "chimera.report_available",
|
|
21034
|
+
payload
|
|
21035
|
+
});
|
|
21036
|
+
}),
|
|
21030
21037
|
events.onPattern("mailbox.received", (_e, payload) => {
|
|
21031
21038
|
broadcast2(clients, { type: "mailbox.received", payload });
|
|
21032
21039
|
}),
|
|
@@ -21543,10 +21550,12 @@ import {
|
|
|
21543
21550
|
} from "@wrongstack/core/utils";
|
|
21544
21551
|
import { makeLightSubagentFactory } from "@wrongstack/runtime";
|
|
21545
21552
|
import {
|
|
21553
|
+
createSageContextMonitorMiddleware,
|
|
21546
21554
|
createSageToolCallMiddleware,
|
|
21547
21555
|
createSageTurnMiddleware,
|
|
21548
21556
|
getSageRetrieval,
|
|
21549
|
-
getSageService
|
|
21557
|
+
getSageService,
|
|
21558
|
+
InjectionTracker
|
|
21550
21559
|
} from "@wrongstack/sage";
|
|
21551
21560
|
|
|
21552
21561
|
// src/server/discover-mailbox-bridge.ts
|
|
@@ -22394,6 +22403,8 @@ async function createAgentServices(input) {
|
|
|
22394
22403
|
installDesignStudioMiddleware({ pipelines, ctx: context });
|
|
22395
22404
|
const memoryRetrieval = getSageRetrieval(memoryStore);
|
|
22396
22405
|
if (config.features.memory !== false && config.Sage?.enabled !== false && memoryRetrieval) {
|
|
22406
|
+
const sageInjectionTracker = new InjectionTracker();
|
|
22407
|
+
const getSageSessionId = () => input.sessionGetter().id;
|
|
22397
22408
|
if (config.Sage?.inject?.toolResults !== false) {
|
|
22398
22409
|
pipelines.toolCall.use(
|
|
22399
22410
|
createSageToolCallMiddleware({
|
|
@@ -22411,7 +22422,9 @@ async function createAgentServices(input) {
|
|
|
22411
22422
|
// middleware falls back to ctx.session.id for cooldown but passes
|
|
22412
22423
|
// undefined to retrieval, causing owned session-scoped memories to be
|
|
22413
22424
|
// silently excluded from tool-call injection.
|
|
22414
|
-
getSessionId:
|
|
22425
|
+
getSessionId: getSageSessionId,
|
|
22426
|
+
tracker: sageInjectionTracker,
|
|
22427
|
+
events
|
|
22415
22428
|
})
|
|
22416
22429
|
);
|
|
22417
22430
|
}
|
|
@@ -22421,10 +22434,19 @@ async function createAgentServices(input) {
|
|
|
22421
22434
|
memory: memoryRetrieval,
|
|
22422
22435
|
maxMemories: config.Sage?.inject?.maxTurnMemories,
|
|
22423
22436
|
maxChars: config.Sage?.inject?.maxCharsPerTurn,
|
|
22424
|
-
minScore: config.Sage?.inject?.minScore
|
|
22437
|
+
minScore: config.Sage?.inject?.minScore,
|
|
22438
|
+
getSessionId: getSageSessionId,
|
|
22439
|
+
tracker: sageInjectionTracker
|
|
22425
22440
|
})
|
|
22426
22441
|
);
|
|
22427
22442
|
}
|
|
22443
|
+
pipelines.request.use(
|
|
22444
|
+
createSageContextMonitorMiddleware({
|
|
22445
|
+
tracker: sageInjectionTracker,
|
|
22446
|
+
events,
|
|
22447
|
+
getSessionId: getSageSessionId
|
|
22448
|
+
})
|
|
22449
|
+
);
|
|
22428
22450
|
}
|
|
22429
22451
|
const codebaseIndexing = setupWebUICodebaseIndexing({
|
|
22430
22452
|
config,
|
package/dist/protocol/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const CLIENT_MESSAGE_TYPES: readonly ["abort", "ping", "user_message", "tool.confirm_result", "completion.request", "model.switch", "model.refine", "autonomy.switch", "context.clear", "context.compact", "context.debug", "context.editor.open", "context.editor.validate", "context.editor.apply", "context.mode.create", "context.mode.delete", "context.mode.switch", "context.mode.update", "context.modes.list", "context.repair", "mode.switch", "modes.list", "session.checkpoints", "session.delete", "session.new", "session.rename", "session.resume", "session.rewind", "session.save", "sessions.list", "side_effects.list", "stats.get", "todo.update", "todos.clear", "todos.get", "todos.remove", "collab.join", "collab.leave", "collab.annotate", "collab.resolve", "collab.request_pause", "collab.resume", "collab.grant_control", "collab.inject_tool", "mailbox.action", "mailbox.agents", "mailbox.clear", "mailbox.compact", "mailbox.messages", "mailbox.purge", "mailbox.send", "files.list", "files.read", "files.tree", "files.write", "git.changes", "git.diff", "git.info", "projects.add", "projects.list", "projects.select", "working_dir.set", "worktree.cleanup", "worktree.diff", "worktree.merge", "worktree.remove", "worktree.scan", "shell.open", "process.kill", "process.killAll", "process.list", "terminal.close", "terminal.create", "terminal.input", "terminal.resize", "codebase.index.server.shutdown", "connections.health", "connections.service_action", "diag.get", "key.add", "key.delete", "key.set_active", "key.update", "prefs.get", "prefs.update", "provider.add", "provider.clear_models", "provider.models", "provider.models.search", "provider.probe", "provider.remove", "provider.status.clear", "provider.status.get", "provider.status.retry", "provider.undo_clear", "provider.update", "providers.list", "providers.saved", "tool.disable", "tool.enable", "tools.list", "webui.shutdown", "goal-state.get", "goal.addTask", "goal.assess", "goal.assignTask", "goal.clear", "goal.get", "goal.list", "goal.load", "goal.moveTask", "goal.pause", "goal.resume", "goal.retryTask", "goal.revert", "goal.runTask", "goal.save", "goal.selectPhase", "goal.start", "goal.state", "goal.status", "goal.stop", "goal.taskStatus", "goal.toggleAutonomous", "plan.get", "plan.item.update", "plan.template_use", "task.update", "tasks.get", "sdd.board.cancel_task", "sdd.board.cleanup_worktrees", "sdd.board.delete_task", "sdd.board.destroy", "sdd.board.get", "sdd.board.list", "sdd.board.pause", "sdd.board.reassign", "sdd.board.resume", "sdd.board.retry", "sdd.board.retry_all_failed", "sdd.board.rollback", "sdd.board.set_task_fallbacks", "sdd.board.set_task_model", "sdd.board.set_task_verification", "sdd.board.split_task", "sdd.board.stop", "sdd.run.from_graph", "sdd.run.from_spec", "sdd.run.start", "sdd.spec.approve", "sdd.spec.discard", "sdd.spec.get", "sdd.spec.message", "sdd.spec.start", "specs.get", "specs.list", "specs.taskStatus", "brain.ask", "brain.config.get", "brain.config.set", "brain.risk", "brain.status", "chronicle.facet", "chronicle.facets", "chronicle.graph", "chronicle.metrics", "chronicle.query", "chronicle.status", "config.doctor", "design.list", "design.materialize", "design.set", "design.state", "design.swap", "design.tune", "design.use", "design.verify", "memory.list", "memory.sage.backfillRecoverable", "memory.sage.candidateResolve", "memory.sage.delete", "memory.sage.forFile", "memory.sage.get", "memory.sage.graph", "memory.sage.list", "memory.sage.listPage", "memory.sage.recover", "memory.sage.remember", "memory.sage.update", "auth.oauth.cancel", "auth.oauth.code", "auth.oauth.start", "mcp.add", "mcp.disable", "mcp.discover", "mcp.enable", "mcp.list", "mcp.prompt.get", "mcp.prompts", "mcp.remove", "mcp.resource.read", "mcp.resources", "mcp.restart", "mcp.sleep", "mcp.update", "mcp.wake", "prompts.content", "prompts.create", "prompts.favorite", "prompts.list", "prompts.recent", "prompts.search", "prompts.used", "skills.content", "skills.create", "skills.edit", "skills.export", "skills.install", "skills.list", "skills.uninstall", "skills.update"];
|
|
2
|
-
export declare const SERVER_MESSAGE_TYPES: readonly ["error", "log", "pong", "side_effects", "agent.status_changed", "agent.timeline.message", "client.status_update", "compaction.failed", "completion.result", "context.compacted", "context.debug", "context.editor.snapshot", "context.editor.validation", "context.editor.applied", "context.mode.changed", "context.modes.list", "context.repaired", "ctx.max_context", "ctx.pct", "delegate.completed", "delegate.started", "iteration.completed", "iteration.limit_reached", "iteration.started", "model.refine_result", "modes.list", "provider.active_blocked", "provider.error", "provider.fallback", "provider.response", "provider.retry", "provider.status_changed", "provider.stream_error", "provider.text_delta", "provider.thinking_delta", "run.result", "session.checkpoints", "session.damaged", "session.end", "session.rewound", "session.start", "session.stats", "sessions.list", "sessions.status_update", "stats.get", "token.cost_estimate_unavailable", "token.threshold", "tool.confirm_needed", "tool.disabled", "tool.enabled", "tool.executed", "tool.loop_detected", "tool.progress", "tool.started", "tools.list", "trust.persisted", "collab.annotation.added", "collab.annotation.resolved", "collab.event", "collab.injection.granted", "collab.participant.joined", "collab.participant.left", "collab.pause.granted", "collab.pause.released", "collab.state", "mailbox.action_result", "mailbox.agent_registered", "mailbox.agents", "mailbox.cleared", "mailbox.compacted", "mailbox.event", "mailbox.messages", "mailbox.sent", "mailbox.purged", "mailbox.received", "subagent.budget_extended", "subagent.event", "checkpoint.written", "codemap.file_event", "codemap.index_updated", "codemap.tool_executed", "codemap.tool_started", "file.saved", "files.list", "files.read", "files.tree", "files.written", "git.changes", "git.diff", "git.info", "process.list", "projects.added", "projects.list", "projects.selected", "terminal.exit", "terminal.output", "working_dir.changed", "worktree.cleanup_result", "worktree.diff_result", "worktree.event", "worktree.merge_result", "worktree.orphans", "worktree.state", "auth.oauth.status", "codebase.index.server.shutdown_result", "connections.health_error", "connections.health_result", "connections.service_action_result", "diag.get", "key.operation_result", "model.switch_result", "prefs.updated", "provider.catalog", "provider.models", "provider.models.search_result", "provider.probe", "provider.status.snapshot", "providers.saved", "budget.decision", "budget.threshold_reached", "coordinator.stats", "coordinator.status", "eternal.iteration", "fleet.concurrency_update", "goal-state.updated", "goal.assess.result", "goal.list", "goal.paused", "goal.resumed", "goal.saved", "goal.error", "goal.stopped", "goal.failed", "goal.completed", "goal.cleared", "goal.reverted", "goal.progress", "goal.state", "in_flight.ended", "in_flight.started", "plan.updated", "task.completed", "task.failed", "task.pending", "task.started", "tasks.updated", "todos.cleared", "todos.updated", "kanban.task.activity", "sdd.board.lifecycle_result", "sdd.board.list", "sdd.board.snapshot", "sdd.run.started", "sdd.spec.agent_text", "sdd.spec.error", "sdd.spec.snapshot", "specs.detail", "specs.list", "consensus.vote_cast", "consensus.vote_initiated", "consensus.vote_resolved", "cron.job_fired", "cron.snapshot", "techstack.job.cancelled", "techstack.job.failed", "techstack.job.progress", "techstack.job.started", "techstack.report.delivered", "techstack.report.ready", "techstack.snapshot.updated", "techstack.workspace.completed", "brain.answer", "brain.config", "brain.event", "brain.status", "chronicle.error", "chronicle.facet_result", "chronicle.facets_result", "chronicle.graph_result", "chronicle.metrics_result", "chronicle.query_result", "chronicle.status_result", "config.doctor.result", "design.list", "design.materialize", "design.set", "design.state", "design.swap", "design.tune", "design.use", "design.verify", "memory.event", "memory.list", "memory.sage.backfillRecoverable", "memory.sage.candidateResolve", "memory.sage.delete", "memory.sage.forFile", "memory.sage.get", "memory.sage.graph", "memory.sage.list", "memory.sage.listPage", "memory.sage.recover", "memory.sage.remember", "memory.sage.update", "mcp.content.error", "mcp.content.selected", "mcp.list", "mcp.operation_result", "mcp.prompts", "mcp.resources", "mcp.server.added", "mcp.server.connected", "mcp.server.disconnected", "mcp.server.discovered", "mcp.server.error", "mcp.server.reconnected", "mcp.server.removed", "mcp.server.sleeping", "mcp.server.updated", "mcp.server.waking", "prompts.content", "prompts.created", "prompts.favorite", "prompts.list", "prompts.recent", "prompts.search", "prompts.used", "skills.content", "skills.created", "skills.edited", "skills.exported", "skills.installed", "skills.list", "skills.uninstalled", "skills.updated"];
|
|
2
|
+
export declare const SERVER_MESSAGE_TYPES: readonly ["error", "log", "pong", "side_effects", "agent.status_changed", "agent.timeline.message", "client.status_update", "chimera.report_available", "compaction.failed", "completion.result", "context.compacted", "context.debug", "context.editor.snapshot", "context.editor.validation", "context.editor.applied", "context.mode.changed", "context.modes.list", "context.repaired", "ctx.max_context", "ctx.pct", "delegate.completed", "delegate.started", "iteration.completed", "iteration.limit_reached", "iteration.started", "model.refine_result", "modes.list", "provider.active_blocked", "provider.error", "provider.fallback", "provider.response", "provider.retry", "provider.status_changed", "provider.stream_error", "provider.text_delta", "provider.thinking_delta", "run.result", "session.checkpoints", "session.damaged", "session.end", "session.rewound", "session.start", "session.stats", "sessions.list", "sessions.status_update", "stats.get", "token.cost_estimate_unavailable", "token.threshold", "tool.confirm_needed", "tool.disabled", "tool.enabled", "tool.executed", "tool.loop_detected", "tool.progress", "tool.started", "tools.list", "trust.persisted", "collab.annotation.added", "collab.annotation.resolved", "collab.event", "collab.injection.granted", "collab.participant.joined", "collab.participant.left", "collab.pause.granted", "collab.pause.released", "collab.state", "mailbox.action_result", "mailbox.agent_registered", "mailbox.agents", "mailbox.cleared", "mailbox.compacted", "mailbox.event", "mailbox.messages", "mailbox.sent", "mailbox.purged", "mailbox.received", "subagent.budget_extended", "subagent.event", "checkpoint.written", "codemap.file_event", "codemap.index_updated", "codemap.tool_executed", "codemap.tool_started", "file.saved", "files.list", "files.read", "files.tree", "files.written", "git.changes", "git.diff", "git.info", "process.list", "projects.added", "projects.list", "projects.selected", "terminal.exit", "terminal.output", "working_dir.changed", "worktree.cleanup_result", "worktree.diff_result", "worktree.event", "worktree.merge_result", "worktree.orphans", "worktree.state", "auth.oauth.status", "codebase.index.server.shutdown_result", "connections.health_error", "connections.health_result", "connections.service_action_result", "diag.get", "key.operation_result", "model.switch_result", "prefs.updated", "provider.catalog", "provider.models", "provider.models.search_result", "provider.probe", "provider.status.snapshot", "providers.saved", "budget.decision", "budget.threshold_reached", "coordinator.stats", "coordinator.status", "eternal.iteration", "fleet.concurrency_update", "goal-state.updated", "goal.assess.result", "goal.list", "goal.paused", "goal.resumed", "goal.saved", "goal.error", "goal.stopped", "goal.failed", "goal.completed", "goal.cleared", "goal.reverted", "goal.progress", "goal.state", "in_flight.ended", "in_flight.started", "plan.updated", "task.completed", "task.failed", "task.pending", "task.started", "tasks.updated", "todos.cleared", "todos.updated", "kanban.task.activity", "sdd.board.lifecycle_result", "sdd.board.list", "sdd.board.snapshot", "sdd.run.started", "sdd.spec.agent_text", "sdd.spec.error", "sdd.spec.snapshot", "specs.detail", "specs.list", "consensus.vote_cast", "consensus.vote_initiated", "consensus.vote_resolved", "cron.job_fired", "cron.snapshot", "techstack.job.cancelled", "techstack.job.failed", "techstack.job.progress", "techstack.job.started", "techstack.report.delivered", "techstack.report.ready", "techstack.snapshot.updated", "techstack.workspace.completed", "brain.answer", "brain.config", "brain.event", "brain.status", "chronicle.error", "chronicle.facet_result", "chronicle.facets_result", "chronicle.graph_result", "chronicle.metrics_result", "chronicle.query_result", "chronicle.status_result", "config.doctor.result", "design.list", "design.materialize", "design.set", "design.state", "design.swap", "design.tune", "design.use", "design.verify", "memory.event", "memory.list", "memory.sage.backfillRecoverable", "memory.sage.candidateResolve", "memory.sage.delete", "memory.sage.forFile", "memory.sage.get", "memory.sage.graph", "memory.sage.list", "memory.sage.listPage", "memory.sage.recover", "memory.sage.remember", "memory.sage.update", "mcp.content.error", "mcp.content.selected", "mcp.list", "mcp.operation_result", "mcp.prompts", "mcp.resources", "mcp.server.added", "mcp.server.connected", "mcp.server.disconnected", "mcp.server.discovered", "mcp.server.error", "mcp.server.reconnected", "mcp.server.removed", "mcp.server.sleeping", "mcp.server.updated", "mcp.server.waking", "prompts.content", "prompts.created", "prompts.favorite", "prompts.list", "prompts.recent", "prompts.search", "prompts.used", "skills.content", "skills.created", "skills.edited", "skills.exported", "skills.installed", "skills.list", "skills.uninstalled", "skills.updated"];
|
|
3
3
|
export type ExactClientMessageType = (typeof CLIENT_MESSAGE_TYPES)[number];
|
|
4
4
|
export type ExactServerMessageType = (typeof SERVER_MESSAGE_TYPES)[number];
|
|
5
5
|
export declare function isRegisteredMessageType(type: string, direction: 'client' | 'server'): boolean;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare const SERVER_CONVERSATION_MESSAGE_TYPES: readonly ['error', 'log', 'pong', 'side_effects', 'agent.status_changed', 'agent.timeline.message', 'client.status_update', 'compaction.failed', 'completion.result', 'context.compacted', 'context.debug', 'context.editor.snapshot', 'context.editor.validation', 'context.editor.applied', 'context.mode.changed', 'context.modes.list', 'context.repaired', 'ctx.max_context', 'ctx.pct', 'delegate.completed', 'delegate.started', 'iteration.completed', 'iteration.limit_reached', 'iteration.started', 'model.refine_result', 'modes.list', 'provider.active_blocked', 'provider.error', 'provider.fallback', 'provider.response', 'provider.retry', 'provider.status_changed', 'provider.stream_error', 'provider.text_delta', 'provider.thinking_delta', 'run.result', 'session.checkpoints', 'session.damaged', 'session.end', 'session.rewound', 'session.start', 'session.stats', 'sessions.list', 'sessions.status_update', 'stats.get', 'token.cost_estimate_unavailable', 'token.threshold', 'tool.confirm_needed', 'tool.disabled', 'tool.enabled', 'tool.executed', 'tool.loop_detected', 'tool.progress', 'tool.started', 'tools.list', 'trust.persisted'];
|
|
1
|
+
export declare const SERVER_CONVERSATION_MESSAGE_TYPES: readonly ['error', 'log', 'pong', 'side_effects', 'agent.status_changed', 'agent.timeline.message', 'client.status_update', 'chimera.report_available', 'compaction.failed', 'completion.result', 'context.compacted', 'context.debug', 'context.editor.snapshot', 'context.editor.validation', 'context.editor.applied', 'context.mode.changed', 'context.modes.list', 'context.repaired', 'ctx.max_context', 'ctx.pct', 'delegate.completed', 'delegate.started', 'iteration.completed', 'iteration.limit_reached', 'iteration.started', 'model.refine_result', 'modes.list', 'provider.active_blocked', 'provider.error', 'provider.fallback', 'provider.response', 'provider.retry', 'provider.status_changed', 'provider.stream_error', 'provider.text_delta', 'provider.thinking_delta', 'run.result', 'session.checkpoints', 'session.damaged', 'session.end', 'session.rewound', 'session.start', 'session.stats', 'sessions.list', 'sessions.status_update', 'stats.get', 'token.cost_estimate_unavailable', 'token.threshold', 'tool.confirm_needed', 'tool.disabled', 'tool.enabled', 'tool.executed', 'tool.loop_detected', 'tool.progress', 'tool.started', 'tools.list', 'trust.persisted'];
|
|
2
2
|
export declare const SERVER_COLLABORATION_MESSAGE_TYPES: readonly ['collab.annotation.added', 'collab.annotation.resolved', 'collab.event', 'collab.injection.granted', 'collab.participant.joined', 'collab.participant.left', 'collab.pause.granted', 'collab.pause.released', 'collab.state', 'mailbox.action_result', 'mailbox.agent_registered', 'mailbox.agents', 'mailbox.cleared', 'mailbox.compacted', 'mailbox.event', 'mailbox.messages', 'mailbox.sent', 'mailbox.purged', 'mailbox.received', 'subagent.budget_extended', 'subagent.event'];
|
|
3
3
|
//# sourceMappingURL=server-conversation.d.ts.map
|
package/dist/server/entry.js
CHANGED
|
@@ -77,8 +77,7 @@ var BOOLEAN_PREF_KEYS = /* @__PURE__ */ new Set([
|
|
|
77
77
|
// Display-only toggles (purely visual, persisted in localStorage via Zustand).
|
|
78
78
|
"groupToolCalls",
|
|
79
79
|
"showThinkingLogs",
|
|
80
|
-
// v11 Display parity:
|
|
81
|
-
"showAgentSwarmPanel",
|
|
80
|
+
// v11 Display parity: inverse fsAccess flag.
|
|
82
81
|
"allowOutsideProjectRoot",
|
|
83
82
|
// v13 Display parity (TUI SettingsPicker fields 42 & 43): the read tool
|
|
84
83
|
// includes codebase-index symbols, and SAGE memory-inject blocks are
|
|
@@ -173,7 +172,8 @@ var ENUM_PREF_KEYS = {
|
|
|
173
172
|
// Chimera autoFix + auto-review cascade threshold
|
|
174
173
|
chimeraAutoFix: /* @__PURE__ */ new Set(["off", "ask", "auto"]),
|
|
175
174
|
autoReviewCascadeOn: /* @__PURE__ */ new Set(["off", "critical", "high"]),
|
|
176
|
-
fleetChatVerbosity: /* @__PURE__ */ new Set(["off", "full"])
|
|
175
|
+
fleetChatVerbosity: /* @__PURE__ */ new Set(["off", "full"]),
|
|
176
|
+
showAgentSwarmPanel: /* @__PURE__ */ new Set(["bottom", "sidebar", "off"])
|
|
177
177
|
};
|
|
178
178
|
function validateModelRuntimeValue(modelRuntime, path30) {
|
|
179
179
|
const reasoning = modelRuntime["reasoning"];
|
|
@@ -8381,7 +8381,7 @@ function buildCspHeader(publicWsUrl, host, port) {
|
|
|
8381
8381
|
if (host && isLoopbackHostname(host)) {
|
|
8382
8382
|
const p = port ?? 3456;
|
|
8383
8383
|
if (p > 0 && p <= 65535) {
|
|
8384
|
-
for (const h of ["127.0.0.1", "localhost"
|
|
8384
|
+
for (const h of ["127.0.0.1", "localhost"]) {
|
|
8385
8385
|
connect.add(`ws://${h}:${p}`);
|
|
8386
8386
|
connect.add(`wss://${h}:${p}`);
|
|
8387
8387
|
}
|
|
@@ -14399,6 +14399,7 @@ var SERVER_CONVERSATION_MESSAGE_TYPES = [
|
|
|
14399
14399
|
"agent.status_changed",
|
|
14400
14400
|
"agent.timeline.message",
|
|
14401
14401
|
"client.status_update",
|
|
14402
|
+
"chimera.report_available",
|
|
14402
14403
|
"compaction.failed",
|
|
14403
14404
|
"completion.result",
|
|
14404
14405
|
"context.compacted",
|
|
@@ -17289,12 +17290,67 @@ var SddWizardWebSocketHandler = class {
|
|
|
17289
17290
|
// src/server/setup-events.ts
|
|
17290
17291
|
import { recordTaskFileActivity } from "@wrongstack/kanban";
|
|
17291
17292
|
|
|
17293
|
+
// src/server/setup-events-core-watchers.ts
|
|
17294
|
+
import * as fs17 from "node:fs/promises";
|
|
17295
|
+
import * as path19 from "node:path";
|
|
17296
|
+
function registerSetupEventsCoreWatchers(deps2) {
|
|
17297
|
+
const { broadcast: broadcast2, clients, context } = deps2;
|
|
17298
|
+
const disposers = [];
|
|
17299
|
+
const conversationState = context.state;
|
|
17300
|
+
if (typeof conversationState?.onChange === "function") {
|
|
17301
|
+
disposers.push(
|
|
17302
|
+
conversationState.onChange((change) => {
|
|
17303
|
+
if (change.kind !== "todos_replaced") return;
|
|
17304
|
+
broadcast2(clients, {
|
|
17305
|
+
type: "todos.updated",
|
|
17306
|
+
payload: {
|
|
17307
|
+
sessionId: context.session?.id ?? "",
|
|
17308
|
+
todos: [...change.todos],
|
|
17309
|
+
revision: conversationState.revision
|
|
17310
|
+
}
|
|
17311
|
+
});
|
|
17312
|
+
})
|
|
17313
|
+
);
|
|
17314
|
+
}
|
|
17315
|
+
const projectRoot = context.projectRoot;
|
|
17316
|
+
if (projectRoot) {
|
|
17317
|
+
disposers.push(
|
|
17318
|
+
subscribeKanbanDaemonEvents(projectRoot, (message) => broadcast2(clients, message))
|
|
17319
|
+
);
|
|
17320
|
+
}
|
|
17321
|
+
return disposers;
|
|
17322
|
+
}
|
|
17323
|
+
function registerSetupEventsClientStatusWriter(deps2) {
|
|
17324
|
+
const { broadcast: broadcast2, clients, events, wpaths } = deps2;
|
|
17325
|
+
const on = (event, listener) => events.on(event, listener);
|
|
17326
|
+
return on("client.status", async (e) => {
|
|
17327
|
+
broadcast2(clients, { type: "client.status_update", payload: e });
|
|
17328
|
+
if (wpaths?.projectStatus) {
|
|
17329
|
+
try {
|
|
17330
|
+
const statusFile = wpaths.projectStatus(e.projectHash);
|
|
17331
|
+
const dir = path19.dirname(statusFile);
|
|
17332
|
+
await fs17.mkdir(dir, { recursive: true });
|
|
17333
|
+
await fs17.writeFile(statusFile, JSON.stringify(e, null, 2), "utf-8");
|
|
17334
|
+
} catch (err) {
|
|
17335
|
+
console.error(
|
|
17336
|
+
JSON.stringify({
|
|
17337
|
+
level: "error",
|
|
17338
|
+
event: "setup_events.status_write_failed",
|
|
17339
|
+
message: err instanceof Error ? err.message : String(err),
|
|
17340
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
17341
|
+
})
|
|
17342
|
+
);
|
|
17343
|
+
}
|
|
17344
|
+
}
|
|
17345
|
+
});
|
|
17346
|
+
}
|
|
17347
|
+
|
|
17292
17348
|
// src/server/setup-events-fleet-broadcaster.ts
|
|
17293
17349
|
import { watch as fsWatch } from "node:fs";
|
|
17294
|
-
import * as
|
|
17350
|
+
import * as path20 from "node:path";
|
|
17295
17351
|
function registerSetupEventsFleetBroadcaster(deps2) {
|
|
17296
17352
|
const { globalConfigPath, wpaths, context, clients, broadcast: broadcast2, onFleetBroadcaster, isDisposed } = deps2;
|
|
17297
|
-
const globalRoot = globalConfigPath ?
|
|
17353
|
+
const globalRoot = globalConfigPath ? path20.dirname(globalConfigPath) : void 0;
|
|
17298
17354
|
if (!globalRoot) return void 0;
|
|
17299
17355
|
const disposers = [];
|
|
17300
17356
|
const broadcastSessions = async () => {
|
|
@@ -17304,8 +17360,8 @@ function registerSetupEventsFleetBroadcaster(deps2) {
|
|
|
17304
17360
|
const sessions = await registry.list();
|
|
17305
17361
|
const ownEntry = sessions.find((s) => s.pid === process.pid);
|
|
17306
17362
|
const mySlug = ownEntry?.projectSlug ?? wpaths?.projectSlug;
|
|
17307
|
-
const myRoot =
|
|
17308
|
-
const live = sessions.filter((s) => s.status === "active" || s.status === "idle").filter((s) => mySlug ? s.projectSlug === mySlug :
|
|
17363
|
+
const myRoot = path20.resolve(context.projectRoot);
|
|
17364
|
+
const live = sessions.filter((s) => s.status === "active" || s.status === "idle").filter((s) => mySlug ? s.projectSlug === mySlug : path20.resolve(s.projectRoot) === myRoot).map((s) => ({
|
|
17309
17365
|
sessionId: s.sessionId,
|
|
17310
17366
|
projectName: s.projectName,
|
|
17311
17367
|
projectSlug: s.projectSlug,
|
|
@@ -17495,14 +17551,14 @@ function createSetupEventSessionHelpers(context, sessionBridge) {
|
|
|
17495
17551
|
|
|
17496
17552
|
// src/server/setup-events-status-watcher.ts
|
|
17497
17553
|
import { watch as fsWatch2 } from "node:fs";
|
|
17498
|
-
import * as
|
|
17499
|
-
import * as
|
|
17554
|
+
import * as fs18 from "node:fs/promises";
|
|
17555
|
+
import * as path22 from "node:path";
|
|
17500
17556
|
|
|
17501
17557
|
// src/server/setup-events-watcher.ts
|
|
17502
|
-
import * as
|
|
17558
|
+
import * as path21 from "node:path";
|
|
17503
17559
|
function statusProjectHashFromWatchFilename(projectsDir, filename) {
|
|
17504
17560
|
const raw = String(filename);
|
|
17505
|
-
const relative5 =
|
|
17561
|
+
const relative5 = path21.isAbsolute(raw) ? path21.relative(projectsDir, raw) : raw;
|
|
17506
17562
|
const parts = relative5.split(/[\\/]+/).filter(Boolean);
|
|
17507
17563
|
if (parts.length < 2 || parts.at(-1) !== "status.json") return null;
|
|
17508
17564
|
return parts.at(-2) ?? null;
|
|
@@ -17537,7 +17593,7 @@ function logFileWatcherMetrics(metrics) {
|
|
|
17537
17593
|
function registerSetupEventsStatusWatcher(deps2) {
|
|
17538
17594
|
const { wpaths, watcherMetrics, clients, broadcast: broadcast2, on, isDisposed } = deps2;
|
|
17539
17595
|
if (!wpaths?.projectStatus || !wpaths.globalRoot) return void 0;
|
|
17540
|
-
const projectsDir =
|
|
17596
|
+
const projectsDir = path22.join(wpaths.globalRoot, "projects");
|
|
17541
17597
|
const knownProjectHashes = /* @__PURE__ */ new Set();
|
|
17542
17598
|
const debounceTimers = /* @__PURE__ */ new Map();
|
|
17543
17599
|
const DEBOUNCE_MS = 150;
|
|
@@ -17582,7 +17638,7 @@ function registerSetupEventsStatusWatcher(deps2) {
|
|
|
17582
17638
|
let watcher;
|
|
17583
17639
|
const startWatcher = async () => {
|
|
17584
17640
|
try {
|
|
17585
|
-
await
|
|
17641
|
+
await fs18.mkdir(projectsDir, { recursive: true });
|
|
17586
17642
|
if (isDisposed()) return;
|
|
17587
17643
|
watcher = fsWatch2(
|
|
17588
17644
|
projectsDir,
|
|
@@ -17596,8 +17652,8 @@ function registerSetupEventsStatusWatcher(deps2) {
|
|
|
17596
17652
|
if (!knownProjectHashes.has(projectHash)) return;
|
|
17597
17653
|
if (watcherMetrics) watcherMetrics.filesProcessed++;
|
|
17598
17654
|
try {
|
|
17599
|
-
const targetFile =
|
|
17600
|
-
const content = await
|
|
17655
|
+
const targetFile = path22.join(projectsDir, projectHash, "status.json");
|
|
17656
|
+
const content = await fs18.readFile(targetFile, "utf-8");
|
|
17601
17657
|
const statusData = JSON.parse(content);
|
|
17602
17658
|
scheduleBroadcast(projectHash, statusData);
|
|
17603
17659
|
} catch {
|
|
@@ -17653,61 +17709,6 @@ function registerSetupEventsStatusWatcher(deps2) {
|
|
|
17653
17709
|
};
|
|
17654
17710
|
}
|
|
17655
17711
|
|
|
17656
|
-
// src/server/setup-events-core-watchers.ts
|
|
17657
|
-
import * as fs18 from "node:fs/promises";
|
|
17658
|
-
import * as path22 from "node:path";
|
|
17659
|
-
function registerSetupEventsCoreWatchers(deps2) {
|
|
17660
|
-
const { broadcast: broadcast2, clients, context } = deps2;
|
|
17661
|
-
const disposers = [];
|
|
17662
|
-
const conversationState = context.state;
|
|
17663
|
-
if (typeof conversationState?.onChange === "function") {
|
|
17664
|
-
disposers.push(
|
|
17665
|
-
conversationState.onChange((change) => {
|
|
17666
|
-
if (change.kind !== "todos_replaced") return;
|
|
17667
|
-
broadcast2(clients, {
|
|
17668
|
-
type: "todos.updated",
|
|
17669
|
-
payload: {
|
|
17670
|
-
sessionId: context.session?.id ?? "",
|
|
17671
|
-
todos: [...change.todos],
|
|
17672
|
-
revision: conversationState.revision
|
|
17673
|
-
}
|
|
17674
|
-
});
|
|
17675
|
-
})
|
|
17676
|
-
);
|
|
17677
|
-
}
|
|
17678
|
-
const projectRoot = context.projectRoot;
|
|
17679
|
-
if (projectRoot) {
|
|
17680
|
-
disposers.push(
|
|
17681
|
-
subscribeKanbanDaemonEvents(projectRoot, (message) => broadcast2(clients, message))
|
|
17682
|
-
);
|
|
17683
|
-
}
|
|
17684
|
-
return disposers;
|
|
17685
|
-
}
|
|
17686
|
-
function registerSetupEventsClientStatusWriter(deps2) {
|
|
17687
|
-
const { broadcast: broadcast2, clients, events, wpaths } = deps2;
|
|
17688
|
-
const on = (event, listener) => events.on(event, listener);
|
|
17689
|
-
return on("client.status", async (e) => {
|
|
17690
|
-
broadcast2(clients, { type: "client.status_update", payload: e });
|
|
17691
|
-
if (wpaths?.projectStatus) {
|
|
17692
|
-
try {
|
|
17693
|
-
const statusFile = wpaths.projectStatus(e.projectHash);
|
|
17694
|
-
const dir = path22.dirname(statusFile);
|
|
17695
|
-
await fs18.mkdir(dir, { recursive: true });
|
|
17696
|
-
await fs18.writeFile(statusFile, JSON.stringify(e, null, 2), "utf-8");
|
|
17697
|
-
} catch (err) {
|
|
17698
|
-
console.error(
|
|
17699
|
-
JSON.stringify({
|
|
17700
|
-
level: "error",
|
|
17701
|
-
event: "setup_events.status_write_failed",
|
|
17702
|
-
message: err instanceof Error ? err.message : String(err),
|
|
17703
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
17704
|
-
})
|
|
17705
|
-
);
|
|
17706
|
-
}
|
|
17707
|
-
}
|
|
17708
|
-
});
|
|
17709
|
-
}
|
|
17710
|
-
|
|
17711
17712
|
// src/server/setup-events.ts
|
|
17712
17713
|
function setupEvents(deps2) {
|
|
17713
17714
|
const {
|
|
@@ -18263,6 +18264,12 @@ function setupEvents(deps2) {
|
|
|
18263
18264
|
});
|
|
18264
18265
|
});
|
|
18265
18266
|
disposers.push(
|
|
18267
|
+
events.onPattern("chimera.report_available", (_event, payload) => {
|
|
18268
|
+
broadcast2(clients, {
|
|
18269
|
+
type: "chimera.report_available",
|
|
18270
|
+
payload
|
|
18271
|
+
});
|
|
18272
|
+
}),
|
|
18266
18273
|
events.onPattern("mailbox.received", (_e, payload) => {
|
|
18267
18274
|
broadcast2(clients, { type: "mailbox.received", payload });
|
|
18268
18275
|
}),
|
|
@@ -18779,10 +18786,12 @@ import {
|
|
|
18779
18786
|
} from "@wrongstack/core/utils";
|
|
18780
18787
|
import { makeLightSubagentFactory } from "@wrongstack/runtime";
|
|
18781
18788
|
import {
|
|
18789
|
+
createSageContextMonitorMiddleware,
|
|
18782
18790
|
createSageToolCallMiddleware,
|
|
18783
18791
|
createSageTurnMiddleware,
|
|
18784
18792
|
getSageRetrieval,
|
|
18785
|
-
getSageService
|
|
18793
|
+
getSageService,
|
|
18794
|
+
InjectionTracker
|
|
18786
18795
|
} from "@wrongstack/sage";
|
|
18787
18796
|
|
|
18788
18797
|
// src/server/discover-mailbox-bridge.ts
|
|
@@ -19630,6 +19639,8 @@ async function createAgentServices(input) {
|
|
|
19630
19639
|
installDesignStudioMiddleware({ pipelines, ctx: context });
|
|
19631
19640
|
const memoryRetrieval = getSageRetrieval(memoryStore);
|
|
19632
19641
|
if (config.features.memory !== false && config.Sage?.enabled !== false && memoryRetrieval) {
|
|
19642
|
+
const sageInjectionTracker = new InjectionTracker();
|
|
19643
|
+
const getSageSessionId = () => input.sessionGetter().id;
|
|
19633
19644
|
if (config.Sage?.inject?.toolResults !== false) {
|
|
19634
19645
|
pipelines.toolCall.use(
|
|
19635
19646
|
createSageToolCallMiddleware({
|
|
@@ -19647,7 +19658,9 @@ async function createAgentServices(input) {
|
|
|
19647
19658
|
// middleware falls back to ctx.session.id for cooldown but passes
|
|
19648
19659
|
// undefined to retrieval, causing owned session-scoped memories to be
|
|
19649
19660
|
// silently excluded from tool-call injection.
|
|
19650
|
-
getSessionId:
|
|
19661
|
+
getSessionId: getSageSessionId,
|
|
19662
|
+
tracker: sageInjectionTracker,
|
|
19663
|
+
events
|
|
19651
19664
|
})
|
|
19652
19665
|
);
|
|
19653
19666
|
}
|
|
@@ -19657,10 +19670,19 @@ async function createAgentServices(input) {
|
|
|
19657
19670
|
memory: memoryRetrieval,
|
|
19658
19671
|
maxMemories: config.Sage?.inject?.maxTurnMemories,
|
|
19659
19672
|
maxChars: config.Sage?.inject?.maxCharsPerTurn,
|
|
19660
|
-
minScore: config.Sage?.inject?.minScore
|
|
19673
|
+
minScore: config.Sage?.inject?.minScore,
|
|
19674
|
+
getSessionId: getSageSessionId,
|
|
19675
|
+
tracker: sageInjectionTracker
|
|
19661
19676
|
})
|
|
19662
19677
|
);
|
|
19663
19678
|
}
|
|
19679
|
+
pipelines.request.use(
|
|
19680
|
+
createSageContextMonitorMiddleware({
|
|
19681
|
+
tracker: sageInjectionTracker,
|
|
19682
|
+
events,
|
|
19683
|
+
getSessionId: getSageSessionId
|
|
19684
|
+
})
|
|
19685
|
+
);
|
|
19664
19686
|
}
|
|
19665
19687
|
const codebaseIndexing = setupWebUICodebaseIndexing({
|
|
19666
19688
|
config,
|
|
@@ -89,7 +89,9 @@ export declare function injectWsConfig(html: string, opts: {
|
|
|
89
89
|
* When set, this origin is added to `connect-src` as a `ws://`/`wss://` entry.
|
|
90
90
|
* @param host - The server bind host. When it matches a known loopback address
|
|
91
91
|
* (`127.0.0.1`, `::1`, `[::1]`, or `localhost`), explicit `ws://`/`wss://`
|
|
92
|
-
* entries for
|
|
92
|
+
* entries for `127.0.0.1` and `localhost` are added to `connect-src`.
|
|
93
|
+
* IPv6 loopback (`[::1]`) is excluded — it produces an invalid CSP source
|
|
94
|
+
* and is covered by `'self'` (CSP maps ws:→http:, wss:→https:).
|
|
93
95
|
* @param port - The server listen port. Defaults to `3456`. Unnecessary when
|
|
94
96
|
* only publicWsUrl is used (no loopback branch).
|
|
95
97
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/webui-server",
|
|
3
|
-
"version": "0.298.
|
|
3
|
+
"version": "0.298.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "WrongStack WebUI HTTP/WebSocket server module — extracted from @wrongstack/webui in PR #243/244 to remove the CLI -> @wrongstack/webui/server cross-package edge (audit §3.1.1). Pure backend: HTTP routes, WebSocket handlers, MCP tool wrappers, HTML serving. The web frontend lives in @wrongstack/webui; this package is the standalone server it can run on.",
|
|
6
6
|
"keywords": [
|
|
@@ -40,18 +40,18 @@
|
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"ws": "^8.21.1",
|
|
43
|
-
"@wrongstack/
|
|
44
|
-
"@wrongstack/
|
|
45
|
-
"@wrongstack/
|
|
46
|
-
"@wrongstack/
|
|
47
|
-
"@wrongstack/
|
|
48
|
-
"@wrongstack/techstack": "0.298.
|
|
49
|
-
"@wrongstack/
|
|
50
|
-
"@wrongstack/
|
|
51
|
-
"@wrongstack/tools": "0.298.
|
|
43
|
+
"@wrongstack/kanban": "0.298.1",
|
|
44
|
+
"@wrongstack/core": "0.298.1",
|
|
45
|
+
"@wrongstack/runtime": "0.298.1",
|
|
46
|
+
"@wrongstack/mcp": "0.298.1",
|
|
47
|
+
"@wrongstack/providers": "0.298.1",
|
|
48
|
+
"@wrongstack/techstack": "0.298.1",
|
|
49
|
+
"@wrongstack/sage": "0.298.1",
|
|
50
|
+
"@wrongstack/sdd": "0.298.1",
|
|
51
|
+
"@wrongstack/tools": "0.298.1"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@types/node": "^26.1.
|
|
54
|
+
"@types/node": "^26.1.2",
|
|
55
55
|
"@types/ws": "^8.18.1",
|
|
56
56
|
"typescript": "^7.0.2"
|
|
57
57
|
},
|