@wrongstack/webui-server 0.284.1 → 0.285.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/dist/index.d.ts +11 -2300
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +1019 -277
  4. package/dist/index.js.map +7 -1
  5. package/dist/server/autophase-routes.d.ts +10 -0
  6. package/dist/server/autophase-routes.d.ts.map +1 -0
  7. package/dist/server/autophase-ws-handler.d.ts +87 -0
  8. package/dist/server/autophase-ws-handler.d.ts.map +1 -0
  9. package/dist/server/backend-services.d.ts +114 -0
  10. package/dist/server/backend-services.d.ts.map +1 -0
  11. package/dist/server/boot.d.ts +19 -0
  12. package/dist/server/boot.d.ts.map +1 -0
  13. package/dist/server/brain-routes.d.ts +9 -0
  14. package/dist/server/brain-routes.d.ts.map +1 -0
  15. package/dist/server/codebase-indexing.d.ts +15 -0
  16. package/dist/server/codebase-indexing.d.ts.map +1 -0
  17. package/dist/server/collaboration-ws-handler.d.ts +159 -0
  18. package/dist/server/collaboration-ws-handler.d.ts.map +1 -0
  19. package/dist/server/completion-handlers.d.ts +39 -0
  20. package/dist/server/completion-handlers.d.ts.map +1 -0
  21. package/dist/server/connection-handler.d.ts +72 -0
  22. package/dist/server/connection-handler.d.ts.map +1 -0
  23. package/dist/server/context-meta.d.ts +28 -0
  24. package/dist/server/context-meta.d.ts.map +1 -0
  25. package/dist/server/custom-context-modes.d.ts +43 -0
  26. package/dist/server/custom-context-modes.d.ts.map +1 -0
  27. package/dist/server/design-handlers.d.ts +40 -0
  28. package/dist/server/design-handlers.d.ts.map +1 -0
  29. package/dist/server/discover-mailbox-bridge.d.ts +26 -0
  30. package/dist/server/discover-mailbox-bridge.d.ts.map +1 -0
  31. package/dist/server/entry.d.ts +2 -2
  32. package/dist/server/entry.d.ts.map +1 -0
  33. package/dist/server/entry.js +811 -300
  34. package/dist/server/entry.js.map +7 -1
  35. package/dist/server/eternal-iteration-broadcast.d.ts +11 -0
  36. package/dist/server/eternal-iteration-broadcast.d.ts.map +1 -0
  37. package/dist/server/file-handlers.d.ts +45 -0
  38. package/dist/server/file-handlers.d.ts.map +1 -0
  39. package/dist/server/file-picker.d.ts +26 -0
  40. package/dist/server/file-picker.d.ts.map +1 -0
  41. package/dist/server/git-handlers.d.ts +55 -0
  42. package/dist/server/git-handlers.d.ts.map +1 -0
  43. package/dist/server/goal-handlers.d.ts +19 -0
  44. package/dist/server/goal-handlers.d.ts.map +1 -0
  45. package/dist/server/handlers/index.d.ts +12 -0
  46. package/dist/server/handlers/index.d.ts.map +1 -0
  47. package/dist/server/handlers/worklist-handlers.d.ts +49 -0
  48. package/dist/server/handlers/worklist-handlers.d.ts.map +1 -0
  49. package/dist/server/handlers.d.ts +1 -51
  50. package/dist/server/handlers.js +17 -8
  51. package/dist/server/handlers.js.map +7 -1
  52. package/dist/server/http-server/analytics-handler.d.ts +35 -0
  53. package/dist/server/http-server/analytics-handler.d.ts.map +1 -0
  54. package/dist/server/http-server/api-handlers.d.ts +44 -0
  55. package/dist/server/http-server/api-handlers.d.ts.map +1 -0
  56. package/dist/server/http-server.d.ts +108 -0
  57. package/dist/server/http-server.d.ts.map +1 -0
  58. package/dist/server/index.d.ts +93 -0
  59. package/dist/server/index.d.ts.map +1 -0
  60. package/dist/server/instance-registry.d.ts +63 -0
  61. package/dist/server/instance-registry.d.ts.map +1 -0
  62. package/dist/server/kanban-routes.d.ts +7 -0
  63. package/dist/server/kanban-routes.d.ts.map +1 -0
  64. package/dist/server/lifecycle.d.ts +51 -0
  65. package/dist/server/lifecycle.d.ts.map +1 -0
  66. package/dist/server/mailbox-handlers.d.ts +51 -0
  67. package/dist/server/mailbox-handlers.d.ts.map +1 -0
  68. package/dist/server/mailbox-routes.d.ts +10 -0
  69. package/dist/server/mailbox-routes.d.ts.map +1 -0
  70. package/dist/server/mcp-handlers.d.ts +46 -0
  71. package/dist/server/mcp-handlers.d.ts.map +1 -0
  72. package/dist/server/mcp-routes.d.ts +37 -0
  73. package/dist/server/mcp-routes.d.ts.map +1 -0
  74. package/dist/server/memory-handlers.d.ts +28 -0
  75. package/dist/server/memory-handlers.d.ts.map +1 -0
  76. package/dist/server/message-dispatcher.d.ts +41 -0
  77. package/dist/server/message-dispatcher.d.ts.map +1 -0
  78. package/dist/server/mode-handlers.d.ts +50 -0
  79. package/dist/server/mode-handlers.d.ts.map +1 -0
  80. package/dist/server/mode-routes.d.ts +8 -0
  81. package/dist/server/mode-routes.d.ts.map +1 -0
  82. package/dist/server/model-auto-discovery.d.ts +9 -0
  83. package/dist/server/model-auto-discovery.d.ts.map +1 -0
  84. package/dist/server/model-catalog.d.ts +16 -0
  85. package/dist/server/model-catalog.d.ts.map +1 -0
  86. package/dist/server/open-browser.d.ts +16 -0
  87. package/dist/server/open-browser.d.ts.map +1 -0
  88. package/dist/server/path-containment.d.ts +3 -0
  89. package/dist/server/path-containment.d.ts.map +1 -0
  90. package/dist/server/pending-confirms.d.ts +14 -0
  91. package/dist/server/pending-confirms.d.ts.map +1 -0
  92. package/dist/server/port-utils.d.ts +28 -0
  93. package/dist/server/port-utils.d.ts.map +1 -0
  94. package/dist/server/pre-context-services.d.ts +58 -0
  95. package/dist/server/pre-context-services.d.ts.map +1 -0
  96. package/dist/server/pref-helpers.d.ts +43 -0
  97. package/dist/server/pref-helpers.d.ts.map +1 -0
  98. package/dist/server/prefs-routes.d.ts +27 -0
  99. package/dist/server/prefs-routes.d.ts.map +1 -0
  100. package/dist/server/process-handlers.d.ts +20 -0
  101. package/dist/server/process-handlers.d.ts.map +1 -0
  102. package/dist/server/project-handlers.d.ts +53 -0
  103. package/dist/server/project-handlers.d.ts.map +1 -0
  104. package/dist/server/project-routes.d.ts +10 -0
  105. package/dist/server/project-routes.d.ts.map +1 -0
  106. package/dist/server/projects-manifest.d.ts +18 -0
  107. package/dist/server/projects-manifest.d.ts.map +1 -0
  108. package/dist/server/prompts-handlers.d.ts +38 -0
  109. package/dist/server/prompts-handlers.d.ts.map +1 -0
  110. package/dist/server/provider-config-io.d.ts +15 -0
  111. package/dist/server/provider-config-io.d.ts.map +1 -0
  112. package/dist/server/provider-config-standalone.d.ts +13 -0
  113. package/dist/server/provider-config-standalone.d.ts.map +1 -0
  114. package/dist/server/provider-handlers.d.ts +74 -0
  115. package/dist/server/provider-handlers.d.ts.map +1 -0
  116. package/dist/server/provider-keys.d.ts +53 -0
  117. package/dist/server/provider-keys.d.ts.map +1 -0
  118. package/dist/server/provider-routes.d.ts +13 -0
  119. package/dist/server/provider-routes.d.ts.map +1 -0
  120. package/dist/server/provider-store.d.ts +26 -0
  121. package/dist/server/provider-store.d.ts.map +1 -0
  122. package/dist/server/routes.d.ts +182 -0
  123. package/dist/server/routes.d.ts.map +1 -0
  124. package/dist/server/sdd-board-routes.d.ts +11 -0
  125. package/dist/server/sdd-board-routes.d.ts.map +1 -0
  126. package/dist/server/sdd-board-ws-handler.d.ts +57 -0
  127. package/dist/server/sdd-board-ws-handler.d.ts.map +1 -0
  128. package/dist/server/sdd-wizard-routes.d.ts +16 -0
  129. package/dist/server/sdd-wizard-routes.d.ts.map +1 -0
  130. package/dist/server/sdd-wizard-wiring.d.ts +26 -0
  131. package/dist/server/sdd-wizard-wiring.d.ts.map +1 -0
  132. package/dist/server/sdd-wizard-ws-handler.d.ts +66 -0
  133. package/dist/server/sdd-wizard-ws-handler.d.ts.map +1 -0
  134. package/dist/server/server-runtime.d.ts +118 -0
  135. package/dist/server/server-runtime.d.ts.map +1 -0
  136. package/dist/server/session-handlers.d.ts +44 -0
  137. package/dist/server/session-handlers.d.ts.map +1 -0
  138. package/dist/server/session-routes.d.ts +23 -0
  139. package/dist/server/session-routes.d.ts.map +1 -0
  140. package/dist/server/setup-events.d.ts +67 -0
  141. package/dist/server/setup-events.d.ts.map +1 -0
  142. package/dist/server/setup-screen.d.ts +44 -0
  143. package/dist/server/setup-screen.d.ts.map +1 -0
  144. package/dist/server/shell-git-routes.d.ts +10 -0
  145. package/dist/server/shell-git-routes.d.ts.map +1 -0
  146. package/dist/server/shell-open.d.ts +12 -0
  147. package/dist/server/shell-open.d.ts.map +1 -0
  148. package/dist/server/skills-handlers.d.ts +77 -0
  149. package/dist/server/skills-handlers.d.ts.map +1 -0
  150. package/dist/server/specs-routes.d.ts +11 -0
  151. package/dist/server/specs-routes.d.ts.map +1 -0
  152. package/dist/server/specs-ws-handler.d.ts +34 -0
  153. package/dist/server/specs-ws-handler.d.ts.map +1 -0
  154. package/dist/server/start-webui.d.ts +29 -0
  155. package/dist/server/start-webui.d.ts.map +1 -0
  156. package/dist/server/terminal-ws-handler.d.ts +70 -0
  157. package/dist/server/terminal-ws-handler.d.ts.map +1 -0
  158. package/dist/server/token-estimator.d.ts +66 -0
  159. package/dist/server/token-estimator.d.ts.map +1 -0
  160. package/dist/server/types.d.ts +143 -0
  161. package/dist/server/types.d.ts.map +1 -0
  162. package/dist/server/usage-cost.d.ts +39 -0
  163. package/dist/server/usage-cost.d.ts.map +1 -0
  164. package/dist/server/worktree-ws-handler.d.ts +67 -0
  165. package/dist/server/worktree-ws-handler.d.ts.map +1 -0
  166. package/dist/server/ws-auth.d.ts +83 -0
  167. package/dist/server/ws-auth.d.ts.map +1 -0
  168. package/dist/server/ws-payload-validation.d.ts +122 -0
  169. package/dist/server/ws-payload-validation.d.ts.map +1 -0
  170. package/dist/server/ws-utils.d.ts +38 -0
  171. package/dist/server/ws-utils.d.ts.map +1 -0
  172. package/dist/server/zip.d.ts +9 -0
  173. package/dist/server/zip.d.ts.map +1 -0
  174. package/package.json +11 -12
package/dist/index.js CHANGED
@@ -1,34 +1,14 @@
1
- import { spawn, spawnSync } from 'child_process';
2
- import { toErrorMessage, wstackGlobalRoot, resolveWstackPaths, atomicWrite as atomicWrite$1 } from '@wrongstack/core/utils';
3
- import { DefaultSecretScrubber, PhaseStore, PhaseGraphBuilder, WorktreeManager, PhaseOrchestrator, AutoPhasePlanner, assignNickname, getDesignState, getDesignKitLoader, isDesignStack, loadActiveKit, setActiveKit, recordKitChoice, applyTokenOverrides, recordOverrides, setDesignOverrides, materializeTokens, runDesignVerify, ToolValidationError, atomicWrite, allServers, ConfigError, DefaultSecretVault, expectDefined, computeTaskProgress, bootConfig as bootConfig$1, resolveProjectDir, GlobalMailbox, createDefaultPipelines, resolveSessionLoggingConfig, createSessionEventBridge, watchProviderConfig, listContextWindowModes, DefaultModelsRegistry, TOKENS, ProviderRegistry, ToolRegistry, DefaultMemoryStore, EventBus, makeMailboxTool, makeMailSendTool, makeMailInboxTool, makeFleetStatusTool, applyToolDescriptionModes, applyToolResultRenderModes, DefaultSessionStore, getSessionRegistry, DEFAULT_SESSION_PRUNE_DAYS, DefaultSessionReader, AnnotationsStore, FleetNotifier, AgentStatusTracker, DefaultModeStore, DefaultSkillLoader, SkillInstaller, DefaultPromptLoader, PromptUsageStore, DefaultSystemPromptBuilder, Context, resolveContextWindowPolicy, CollaborationBus, collabInjectMiddleware, collabPauseMiddleware, installDesignStudioMiddleware, createStrategyCompactor, AutoCompactionMiddleware, estimateRequestTokensCalibrated, ToolExecutor, DEFAULT_TOOLS_CONFIG, Agent, ObservableBrainArbiter, createTieredBrainArbiter, DefaultBrainArbiter, BrainMonitor, mailboxSessionTag, wstackGlobalRoot as wstackGlobalRoot$1, createAutonomyBrain, DEFAULT_CONTEXT_WINDOW_MODE_ID, repairToolUseAdjacency, resolveWstackPaths as resolveWstackPaths$1, recentTextTurns, gatedEnhancerReasoning, enhanceUserPrompt, resolveProviderModelList, projectSlug, deserializeTaskGraph, serializeTaskGraph } from '@wrongstack/core';
4
- import * as path5 from 'path';
5
- import path5__default, { resolve, join, sep, dirname } from 'path';
6
- import { searchCodebaseIndex } from '@wrongstack/tools/codebase-index/index';
7
- import { randomBytes, timingSafeEqual, randomUUID } from 'crypto';
8
- import { WebSocket, WebSocketServer } from 'ws';
9
- import * as fs4 from 'fs/promises';
10
- import * as http from 'http';
11
- import { Buffer } from 'buffer';
12
- import * as os from 'os';
13
- import { listMcp, addMcp, updateMcp, removeMcp, enableMcp, disableMcp, restartMcp, discoverMcp, MCPRegistry } from '@wrongstack/mcp';
14
- import * as net from 'net';
15
- import { decryptConfigSecrets, encryptConfigSecrets } from '@wrongstack/core/security';
16
- import { SddBoardStore, applySddLifecycle, SddRunRegistry, SddInterviewDriver, cleanupStaleSddWorktrees, makeCommandVerifier, SddSupervisor, makeLlmSubtaskGenerator, startSddRun, TaskGraphStore, SpecStore } from '@wrongstack/sdd';
17
- import * as fs12 from 'fs';
18
- import { promises, watch, existsSync } from 'fs';
19
- import JSZip from 'jszip';
20
- import { createRequire } from 'module';
21
- import { fileURLToPath } from 'url';
22
- import { capabilitiesFor, makeProviderFromConfig, buildProviderFactoriesFromRegistry, discoverOpenAICompatibleModels, COMPATIBLE_PRESETS } from '@wrongstack/providers';
23
- import { DefaultTokenCounter } from '@wrongstack/core/infrastructure';
24
- import { createDefaultContainer, makeLightSubagentFactory } from '@wrongstack/runtime';
25
- import { runStartupIndex, isIndexableFile, enqueueReindex, cancelPendingReindexes, shutdownCodebaseIndexHost, ensureSessionShell, builtinToolsPack, rememberTool, forgetTool, searchMemoryTool, relatedMemoryTool, configureExecPolicy, configureDangerBypass } from '@wrongstack/tools';
26
- import { readLiveLock } from '@wrongstack/core/coordination';
27
- import { removeColumn, addColumn, getTask, removeTask, assignTask, updateGoalMetricOnTask, addGoalMetricToTask, releaseTaskClaim, claimReadyTask, getTaskChain, setTaskChain, copyTaskToBoard, transferTaskToBoard, moveTask, updateTask, mergeTasks, splitTask, addTask, syncBoardFromTaskGraph, exportBoardToTaskGraph, getKanbanOrchestrationSnapshot, listReadyTasks, createBoard, generateBoardFromDescription, parseLinesIntoTasks, getBoard, removeBoard, duplicateBoard, updateBoard, getKanbanQueueHealth, listBoards } from '@wrongstack/kanban';
28
- import { beginOAuthLogin } from '@wrongstack/providers/oauth';
29
- import { probeLocalLlm } from '@wrongstack/runtime/probe';
30
-
31
1
  // src/server/autophase-ws-handler.ts
2
+ import { spawnSync } from "node:child_process";
3
+ import { toErrorMessage } from "@wrongstack/core/utils";
4
+ import {
5
+ assignNickname,
6
+ AutoPhasePlanner,
7
+ PhaseGraphBuilder,
8
+ PhaseOrchestrator,
9
+ PhaseStore,
10
+ WorktreeManager
11
+ } from "@wrongstack/core";
32
12
  function deriveTitle(goal) {
33
13
  const firstLine = goal.split("\n").map((l) => l.trim()).find(Boolean);
34
14
  if (!firstLine) return "AutoPhase";
@@ -519,6 +499,14 @@ Type: ${task.type}`;
519
499
  }
520
500
  }
521
501
  };
502
+
503
+ // src/server/completion-handlers.ts
504
+ import * as path from "node:path";
505
+ import { searchCodebaseIndex } from "@wrongstack/tools/codebase-index/index";
506
+
507
+ // src/server/ws-utils.ts
508
+ import { randomBytes } from "node:crypto";
509
+ import { WebSocket } from "ws";
522
510
  function send(ws, msg) {
523
511
  if (ws.readyState === WebSocket.OPEN) {
524
512
  ws.send(JSON.stringify(msg));
@@ -650,8 +638,8 @@ async function handleCompletionRequest(ws, msg, opts) {
650
638
  return;
651
639
  }
652
640
  const payload = parsed.payload;
653
- const projectRoot = path5.resolve(opts.projectRoot);
654
- const resolved = path5.resolve(projectRoot, payload.filePath);
641
+ const projectRoot = path.resolve(opts.projectRoot);
642
+ const resolved = path.resolve(projectRoot, payload.filePath);
655
643
  if (!isInside(projectRoot, resolved)) {
656
644
  send(ws, {
657
645
  type: "completion.result",
@@ -1050,7 +1038,7 @@ function buildSearchQuery(linePrefix, filePath) {
1050
1038
  if (memberMatch?.[1]) return memberMatch[1];
1051
1039
  const token = linePrefix.match(/([A-Za-z_$][\w$]*)$/)?.[1];
1052
1040
  if (token && token.length >= 2) return token;
1053
- return path5.basename(filePath, path5.extname(filePath));
1041
+ return path.basename(filePath, path.extname(filePath));
1054
1042
  }
1055
1043
  function currentLinePrefix(prefix) {
1056
1044
  const idx = Math.max(prefix.lastIndexOf("\n"), prefix.lastIndexOf("\r"));
@@ -1080,11 +1068,16 @@ function head(value, max) {
1080
1068
  return value.length <= max ? value : value.slice(0, max);
1081
1069
  }
1082
1070
  function isInside(root, target) {
1083
- return target === root || target.startsWith(root + path5.sep);
1071
+ return target === root || target.startsWith(root + path.sep);
1084
1072
  }
1073
+
1074
+ // src/server/custom-context-modes.ts
1075
+ import { listContextWindowModes, atomicWrite } from "@wrongstack/core";
1076
+ import * as fs from "node:fs/promises";
1077
+ import * as path2 from "node:path";
1085
1078
  var STORE_FILENAME = "custom-context-modes.json";
1086
1079
  function storePath(wrongstackDir) {
1087
- return path5.join(wrongstackDir, STORE_FILENAME);
1080
+ return path2.join(wrongstackDir, STORE_FILENAME);
1088
1081
  }
1089
1082
  var BUILTIN_IDS = /* @__PURE__ */ new Set(["balanced", "frugal", "deep", "archival"]);
1090
1083
  function createCustomModeStore(wrongstackDir) {
@@ -1092,7 +1085,7 @@ function createCustomModeStore(wrongstackDir) {
1092
1085
  const load2 = async () => {
1093
1086
  modes.clear();
1094
1087
  try {
1095
- const raw = await fs4.readFile(storePath(wrongstackDir), "utf8");
1088
+ const raw = await fs.readFile(storePath(wrongstackDir), "utf8");
1096
1089
  const parsed = JSON.parse(raw);
1097
1090
  if (Array.isArray(parsed.modes)) {
1098
1091
  for (const m of parsed.modes) {
@@ -1197,6 +1190,23 @@ function createCustomModeStore(wrongstackDir) {
1197
1190
  };
1198
1191
  return { modes, load: load2, save: save2, create, update, remove, list };
1199
1192
  }
1193
+
1194
+ // src/server/design-handlers.ts
1195
+ import * as fs2 from "node:fs/promises";
1196
+ import * as path3 from "node:path";
1197
+ import {
1198
+ applyTokenOverrides,
1199
+ getDesignKitLoader,
1200
+ getDesignState,
1201
+ isDesignStack,
1202
+ loadActiveKit,
1203
+ materializeTokens,
1204
+ recordKitChoice,
1205
+ recordOverrides,
1206
+ runDesignVerify,
1207
+ setActiveKit,
1208
+ setDesignOverrides
1209
+ } from "@wrongstack/core";
1200
1210
  function readOverrides(value) {
1201
1211
  const out = {};
1202
1212
  if (value && typeof value === "object") {
@@ -1344,9 +1354,9 @@ async function handleDesignMaterialize(ws, ctx, msg) {
1344
1354
  kitId: active.kit,
1345
1355
  outPath: typeof payload.out === "string" ? payload.out : void 0
1346
1356
  });
1347
- const abs = path5.join(ctx.projectRoot, result.path);
1348
- await fs4.mkdir(path5.dirname(abs), { recursive: true });
1349
- await fs4.writeFile(abs, result.content);
1357
+ const abs = path3.join(ctx.projectRoot, result.path);
1358
+ await fs2.mkdir(path3.dirname(abs), { recursive: true });
1359
+ await fs2.writeFile(abs, result.content);
1350
1360
  send(ws, {
1351
1361
  type: "design.materialize",
1352
1362
  payload: { ok: true, path: result.path, format: result.format, stack }
@@ -1405,6 +1415,11 @@ function createEternalSubscription(subscribe, broadcast2, clientsRef) {
1405
1415
  };
1406
1416
  }
1407
1417
 
1418
+ // src/server/file-handlers.ts
1419
+ import * as fs4 from "node:fs/promises";
1420
+ import * as path5 from "node:path";
1421
+ import { atomicWrite as atomicWrite2, ToolValidationError as ToolValidationError2 } from "@wrongstack/core";
1422
+
1408
1423
  // src/server/file-picker.ts
1409
1424
  var SKIP_DIRS = /* @__PURE__ */ new Set([
1410
1425
  ".git",
@@ -1452,15 +1467,20 @@ function rankFiles(paths, query, limit) {
1452
1467
  scored.sort((a, b) => b.score - a.score || a.path.localeCompare(b.path));
1453
1468
  return scored.slice(0, limit).map((s) => s.path);
1454
1469
  }
1470
+
1471
+ // src/server/path-containment.ts
1472
+ import * as fs3 from "node:fs/promises";
1473
+ import * as path4 from "node:path";
1474
+ import { ToolValidationError } from "@wrongstack/core";
1455
1475
  function isPathInside(root, target) {
1456
- const relative4 = path5.relative(root, target);
1457
- return relative4 === "" || !relative4.startsWith("..") && !path5.isAbsolute(relative4);
1476
+ const relative4 = path4.relative(root, target);
1477
+ return relative4 === "" || !relative4.startsWith("..") && !path4.isAbsolute(relative4);
1458
1478
  }
1459
1479
  async function resolveWorkingDirInsideProject(projectRoot, inputPath) {
1460
- const resolved = path5.resolve(projectRoot, inputPath);
1480
+ const resolved = path4.resolve(projectRoot, inputPath);
1461
1481
  let stat2;
1462
1482
  try {
1463
- stat2 = await fs4.stat(resolved);
1483
+ stat2 = await fs3.stat(resolved);
1464
1484
  } catch {
1465
1485
  throw new ToolValidationError({
1466
1486
  message: `Directory not found or not accessible: ${resolved}`,
@@ -1474,8 +1494,8 @@ async function resolveWorkingDirInsideProject(projectRoot, inputPath) {
1474
1494
  });
1475
1495
  }
1476
1496
  const [realProjectRoot, realResolved] = await Promise.all([
1477
- fs4.realpath(projectRoot),
1478
- fs4.realpath(resolved)
1497
+ fs3.realpath(projectRoot),
1498
+ fs3.realpath(resolved)
1479
1499
  ]);
1480
1500
  if (!isPathInside(realProjectRoot, realResolved)) {
1481
1501
  throw new ToolValidationError({
@@ -1490,14 +1510,14 @@ async function resolveWorkingDirInsideProject(projectRoot, inputPath) {
1490
1510
  async function resolveFileInsideProject(projectRoot, filePath) {
1491
1511
  const resolved = path5.resolve(projectRoot, filePath);
1492
1512
  if (!isPathInside(projectRoot, resolved)) {
1493
- throw new ToolValidationError({ message: "Path outside project root", field: "path" });
1513
+ throw new ToolValidationError2({ message: "Path outside project root", field: "path" });
1494
1514
  }
1495
1515
  const { parent, base } = splitParentAndBase(resolved);
1496
1516
  const realProjectRoot = await fs4.realpath(projectRoot);
1497
1517
  const realParent = await realpathAllowMissing(parent);
1498
1518
  const realFull = path5.join(realParent, base);
1499
1519
  if (!isPathInside(realProjectRoot, realFull)) {
1500
- throw new ToolValidationError({ message: "Path outside project root", field: "path" });
1520
+ throw new ToolValidationError2({ message: "Path outside project root", field: "path" });
1501
1521
  }
1502
1522
  return realFull;
1503
1523
  }
@@ -1517,7 +1537,7 @@ async function realpathAllowMissing(p) {
1517
1537
  while (true) {
1518
1538
  const parent = path5.dirname(cursor);
1519
1539
  if (parent === cursor) {
1520
- throw new ToolValidationError({ message: "Path outside project root", field: "path" });
1540
+ throw new ToolValidationError2({ message: "Path outside project root", field: "path" });
1521
1541
  }
1522
1542
  segments.unshift(path5.basename(cursor));
1523
1543
  try {
@@ -1650,7 +1670,7 @@ async function handleFilesWrite(ws, msg, projectRoot, opts = {}) {
1650
1670
  return;
1651
1671
  }
1652
1672
  try {
1653
- await atomicWrite(realResolved, content);
1673
+ await atomicWrite2(realResolved, content);
1654
1674
  send(ws, { type: "files.written", payload: { filePath, success: true } });
1655
1675
  if (opts.onWritten) {
1656
1676
  void Promise.resolve(opts.onWritten(realResolved)).catch(() => void 0);
@@ -1714,10 +1734,13 @@ async function handleFilesList(ws, msg, projectRoot) {
1714
1734
  payload: { files: rankFiles(results, payload.query ?? "", limit) }
1715
1735
  });
1716
1736
  }
1737
+
1738
+ // src/server/git-handlers.ts
1739
+ import nodePath from "node:path";
1717
1740
  async function handleGitInfo(ws, projectRoot) {
1718
1741
  const cwd = projectRoot || void 0;
1719
1742
  try {
1720
- const { execFile: ef } = await import('child_process');
1743
+ const { execFile: ef } = await import("node:child_process");
1721
1744
  const git = (args) => new Promise((resolve10) => {
1722
1745
  ef("git", args, { cwd, timeout: 3e3 }, (err, stdout) => {
1723
1746
  resolve10(err ? "" : stdout.trim());
@@ -1745,7 +1768,7 @@ async function handleGitInfo(ws, projectRoot) {
1745
1768
  }
1746
1769
  function makeGit(cwd) {
1747
1770
  return async (args) => {
1748
- const { execFile: ef } = await import('child_process');
1771
+ const { execFile: ef } = await import("node:child_process");
1749
1772
  return new Promise((resolve10) => {
1750
1773
  ef(
1751
1774
  "git",
@@ -1827,14 +1850,14 @@ var MAX_DIFF_BYTES = 2 * 1024 * 1024;
1827
1850
  async function handleGitDiff(ws, projectRoot, path23) {
1828
1851
  const cwd = projectRoot || void 0;
1829
1852
  const reply = (extra) => send(ws, { type: "git.diff", payload: { path: path23, ...extra } });
1830
- if (!path23 || path23.includes("\0") || path23.includes("..") || path5__default.isAbsolute(path23)) {
1853
+ if (!path23 || path23.includes("\0") || path23.includes("..") || nodePath.isAbsolute(path23)) {
1831
1854
  reply({ oldText: "", newText: "", error: "invalid path" });
1832
1855
  return;
1833
1856
  }
1834
1857
  try {
1835
1858
  const git = makeGit(cwd);
1836
- const { readFile: readFile11 } = await import('fs/promises');
1837
- const { join: join15 } = await import('path');
1859
+ const { readFile: readFile11 } = await import("node:fs/promises");
1860
+ const { join: join15 } = await import("node:path");
1838
1861
  const oldText = await git(["show", `HEAD:${path23}`]);
1839
1862
  let newText = "";
1840
1863
  try {
@@ -1866,6 +1889,11 @@ async function handleGitDiff(ws, projectRoot, path23) {
1866
1889
  }
1867
1890
  }
1868
1891
 
1892
+ // src/server/http-server.ts
1893
+ import * as fs5 from "node:fs/promises";
1894
+ import * as http from "node:http";
1895
+ import * as path6 from "node:path";
1896
+
1869
1897
  // src/server/http-server/api-handlers.ts
1870
1898
  async function handleApiSessions(res, globalRoot) {
1871
1899
  if (!globalRoot) {
@@ -1874,7 +1902,7 @@ async function handleApiSessions(res, globalRoot) {
1874
1902
  return;
1875
1903
  }
1876
1904
  try {
1877
- const { SessionRegistry } = await import('@wrongstack/core');
1905
+ const { SessionRegistry } = await import("@wrongstack/core");
1878
1906
  const registry = new SessionRegistry(globalRoot);
1879
1907
  const sessions = await registry.list();
1880
1908
  const result = sessions.map((s) => ({
@@ -1912,7 +1940,7 @@ async function handleApiSessionAgents(res, globalRoot, sessionId) {
1912
1940
  return;
1913
1941
  }
1914
1942
  try {
1915
- const { SessionRegistry } = await import('@wrongstack/core');
1943
+ const { SessionRegistry } = await import("@wrongstack/core");
1916
1944
  const registry = new SessionRegistry(globalRoot);
1917
1945
  const entry = await registry.get(sessionId);
1918
1946
  if (!entry) {
@@ -2052,7 +2080,7 @@ async function handleApiSessionEvents(res, globalRoot, sessionId, limit) {
2052
2080
  return;
2053
2081
  }
2054
2082
  try {
2055
- const { SessionRegistry, resolveWstackPaths: resolveWstackPaths3, DefaultSessionStore: DefaultSessionStore2, DefaultSessionReader: DefaultSessionReader2 } = await import('@wrongstack/core');
2083
+ const { SessionRegistry, resolveWstackPaths: resolveWstackPaths3, DefaultSessionStore: DefaultSessionStore2, DefaultSessionReader: DefaultSessionReader2 } = await import("@wrongstack/core");
2056
2084
  const registry = new SessionRegistry(globalRoot);
2057
2085
  const entry = await registry.get(sessionId);
2058
2086
  if (!entry) {
@@ -2134,7 +2162,7 @@ async function handleApiSessionMessage(res, req, globalRoot, sessionId) {
2134
2162
  const priority = ["low", "normal", "high"].includes(rawPriority) ? rawPriority : "high";
2135
2163
  const subject = typeof body["subject"] === "string" && body["subject"].trim() ? body["subject"].trim() : "Message from Fleet HQ";
2136
2164
  try {
2137
- const { SessionRegistry, resolveWstackPaths: resolveWstackPaths3, GlobalMailbox: GlobalMailbox4, mailboxSessionTag: mailboxSessionTag2 } = await import('@wrongstack/core');
2165
+ const { SessionRegistry, resolveWstackPaths: resolveWstackPaths3, GlobalMailbox: GlobalMailbox4, mailboxSessionTag: mailboxSessionTag2 } = await import("@wrongstack/core");
2138
2166
  const registry = new SessionRegistry(globalRoot);
2139
2167
  const entry = await registry.get(sessionId);
2140
2168
  if (!entry) {
@@ -2160,7 +2188,7 @@ async function handleApiSessionMailbox(res, globalRoot, sessionId) {
2160
2188
  return;
2161
2189
  }
2162
2190
  try {
2163
- const { SessionRegistry, resolveWstackPaths: resolveWstackPaths3, GlobalMailbox: GlobalMailbox4, mailboxSessionTag: mailboxSessionTag2 } = await import('@wrongstack/core');
2191
+ const { SessionRegistry, resolveWstackPaths: resolveWstackPaths3, GlobalMailbox: GlobalMailbox4, mailboxSessionTag: mailboxSessionTag2 } = await import("@wrongstack/core");
2164
2192
  const registry = new SessionRegistry(globalRoot);
2165
2193
  const entry = await registry.get(sessionId);
2166
2194
  if (!entry) {
@@ -2218,7 +2246,7 @@ async function handleApiSessionInterrupt(res, req, globalRoot, sessionId) {
2218
2246
  const reason = typeof body["reason"] === "string" && body["reason"].trim() ? body["reason"].trim() : "Operator requested stop from Fleet HQ";
2219
2247
  const from = typeof body["from"] === "string" && body["from"].trim() ? body["from"].trim() : "human@webui";
2220
2248
  try {
2221
- const { SessionRegistry, resolveWstackPaths: resolveWstackPaths3, GlobalMailbox: GlobalMailbox4, mailboxSessionTag: mailboxSessionTag2 } = await import('@wrongstack/core');
2249
+ const { SessionRegistry, resolveWstackPaths: resolveWstackPaths3, GlobalMailbox: GlobalMailbox4, mailboxSessionTag: mailboxSessionTag2 } = await import("@wrongstack/core");
2222
2250
  const registry = new SessionRegistry(globalRoot);
2223
2251
  const entry = await registry.get(sessionId);
2224
2252
  if (!entry) {
@@ -2266,7 +2294,7 @@ async function handleApiFleetBroadcast(res, req, globalRoot) {
2266
2294
  }
2267
2295
  const from = typeof body["from"] === "string" && body["from"].trim() ? body["from"].trim() : "human@webui";
2268
2296
  try {
2269
- const { SessionRegistry, resolveWstackPaths: resolveWstackPaths3, GlobalMailbox: GlobalMailbox4, mailboxSessionTag: mailboxSessionTag2 } = await import('@wrongstack/core');
2297
+ const { SessionRegistry, resolveWstackPaths: resolveWstackPaths3, GlobalMailbox: GlobalMailbox4, mailboxSessionTag: mailboxSessionTag2 } = await import("@wrongstack/core");
2270
2298
  const registry = new SessionRegistry(globalRoot);
2271
2299
  const all = await registry.list();
2272
2300
  const mySlug = all.find((s) => s.pid === process.pid)?.projectSlug;
@@ -2422,6 +2450,10 @@ function clearAnalyticsBuffer() {
2422
2450
  function getAnalyticsBuffer() {
2423
2451
  return [...EVENT_BUFFER];
2424
2452
  }
2453
+
2454
+ // src/server/ws-auth.ts
2455
+ import { Buffer as Buffer2 } from "node:buffer";
2456
+ import { timingSafeEqual } from "node:crypto";
2425
2457
  function isLoopbackHostname(hostname) {
2426
2458
  return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]";
2427
2459
  }
@@ -2450,8 +2482,8 @@ function allowedHostname(hostname, allowedHostnames) {
2450
2482
  }
2451
2483
  function tokenMatches(provided, expected) {
2452
2484
  if (!provided) return false;
2453
- const a = Buffer.from(provided);
2454
- const b = Buffer.from(expected);
2485
+ const a = Buffer2.from(provided);
2486
+ const b = Buffer2.from(expected);
2455
2487
  if (a.length !== b.length) return false;
2456
2488
  return timingSafeEqual(a, b);
2457
2489
  }
@@ -2607,9 +2639,9 @@ function buildCspHeader(wsPort, requestHost, publicWsUrl) {
2607
2639
  return `default-src 'self'; script-src ${scriptSrc}; style-src 'self' 'unsafe-inline'; connect-src ${Array.from(connect).join(" ")}; img-src 'self' data:; font-src 'self' data:; worker-src 'self' blob:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; form-action 'self'`;
2608
2640
  }
2609
2641
  function isInsideDist(candidate, distDir) {
2610
- const root = path5.resolve(distDir);
2611
- const resolved = path5.resolve(candidate);
2612
- return resolved === root || resolved.startsWith(root + path5.sep);
2642
+ const root = path6.resolve(distDir);
2643
+ const resolved = path6.resolve(candidate);
2644
+ return resolved === root || resolved.startsWith(root + path6.sep);
2613
2645
  }
2614
2646
  function decodeSessionId(segment) {
2615
2647
  try {
@@ -2620,7 +2652,7 @@ function decodeSessionId(segment) {
2620
2652
  }
2621
2653
  function createHttpServer(opts) {
2622
2654
  const port = opts.port ?? Number.parseInt(process.env["PORT"] ?? "3456", 10);
2623
- const distDir = path5.resolve(opts.distDir);
2655
+ const distDir = path6.resolve(opts.distDir);
2624
2656
  const wsPort = opts.wsPort;
2625
2657
  const requireAccessToken = Boolean(opts.requireToken) || !isLoopbackBind(opts.host);
2626
2658
  return http.createServer(async (req, res) => {
@@ -2797,21 +2829,21 @@ function createHttpServer(opts) {
2797
2829
  }
2798
2830
  let filePath;
2799
2831
  if (url.pathname === "/" || url.pathname === "") {
2800
- filePath = path5.join(distDir, "index.html");
2832
+ filePath = path6.join(distDir, "index.html");
2801
2833
  } else if (url.pathname.startsWith("/assets/")) {
2802
- filePath = path5.join(distDir, url.pathname);
2834
+ filePath = path6.join(distDir, url.pathname);
2803
2835
  } else if (url.pathname.startsWith("/")) {
2804
- filePath = path5.join(distDir, url.pathname);
2836
+ filePath = path6.join(distDir, url.pathname);
2805
2837
  } else {
2806
- filePath = path5.join(distDir, "index.html");
2838
+ filePath = path6.join(distDir, "index.html");
2807
2839
  }
2808
- const resolvedPath = path5.resolve(filePath);
2840
+ const resolvedPath = path6.resolve(filePath);
2809
2841
  if (!isInsideDist(resolvedPath, distDir)) {
2810
2842
  res.writeHead(403, { "Content-Type": "text/plain" });
2811
2843
  res.end("Forbidden");
2812
2844
  return;
2813
2845
  }
2814
- const ext = path5.extname(resolvedPath);
2846
+ const ext = path6.extname(resolvedPath);
2815
2847
  const contentType = MIME_TYPES[ext] ?? "application/octet-stream";
2816
2848
  res.setHeader("Content-Type", contentType);
2817
2849
  res.setHeader("X-Content-Type-Options", "nosniff");
@@ -2823,18 +2855,18 @@ function createHttpServer(opts) {
2823
2855
  "Content-Security-Policy",
2824
2856
  buildCspHeader(wsPort, requestHostForCsp(req.headers.host), opts.publicWsUrl)
2825
2857
  );
2826
- const html = await fs4.readFile(resolvedPath, "utf8");
2858
+ const html = await fs5.readFile(resolvedPath, "utf8");
2827
2859
  res.writeHead(200);
2828
2860
  res.end(injectWsConfig(html, { wsPort, publicWsUrl: opts.publicWsUrl }));
2829
2861
  return;
2830
2862
  }
2831
- const fileContent = await fs4.readFile(resolvedPath);
2863
+ const fileContent = await fs5.readFile(resolvedPath);
2832
2864
  res.writeHead(200);
2833
2865
  res.end(fileContent);
2834
2866
  } catch (err) {
2835
2867
  if (err.code === "ENOENT") {
2836
2868
  try {
2837
- const html = await fs4.readFile(path5.join(distDir, "index.html"), "utf8");
2869
+ const html = await fs5.readFile(path6.join(distDir, "index.html"), "utf8");
2838
2870
  res.writeHead(200, {
2839
2871
  "Content-Type": "text/html",
2840
2872
  "X-Content-Type-Options": "nosniff",
@@ -2858,11 +2890,17 @@ function createHttpServer(opts) {
2858
2890
  }
2859
2891
  });
2860
2892
  }
2893
+
2894
+ // src/server/instance-registry.ts
2895
+ import * as os from "node:os";
2896
+ import * as path7 from "node:path";
2897
+ import * as fs6 from "node:fs/promises";
2898
+ import { atomicWrite as atomicWrite3 } from "@wrongstack/core";
2861
2899
  function defaultBaseDir() {
2862
- return path5.join(os.homedir(), ".wrongstack");
2900
+ return path7.join(os.homedir(), ".wrongstack");
2863
2901
  }
2864
2902
  function registryPath(baseDir = defaultBaseDir()) {
2865
- return path5.join(baseDir, "webui-instances.json");
2903
+ return path7.join(baseDir, "webui-instances.json");
2866
2904
  }
2867
2905
  function isPidAlive(pid) {
2868
2906
  if (!Number.isInteger(pid) || pid <= 0) return false;
@@ -2875,7 +2913,7 @@ function isPidAlive(pid) {
2875
2913
  }
2876
2914
  async function load(file) {
2877
2915
  try {
2878
- const raw = await fs4.readFile(file, "utf8");
2916
+ const raw = await fs6.readFile(file, "utf8");
2879
2917
  const parsed = JSON.parse(raw);
2880
2918
  if (parsed?.version === 1 && Array.isArray(parsed.instances)) {
2881
2919
  return parsed;
@@ -2885,7 +2923,7 @@ async function load(file) {
2885
2923
  return { version: 1, instances: [] };
2886
2924
  }
2887
2925
  async function save(file, instances) {
2888
- await atomicWrite(file, `${JSON.stringify({ version: 1, instances }, null, 2)}
2926
+ await atomicWrite3(file, `${JSON.stringify({ version: 1, instances }, null, 2)}
2889
2927
  `, {
2890
2928
  mode: 384
2891
2929
  });
@@ -2930,6 +2968,19 @@ function formatInstances(instances) {
2930
2968
  }
2931
2969
  return lines.join("\n");
2932
2970
  }
2971
+
2972
+ // src/server/mcp-handlers.ts
2973
+ import { allServers } from "@wrongstack/core";
2974
+ import {
2975
+ addMcp,
2976
+ disableMcp,
2977
+ discoverMcp,
2978
+ enableMcp,
2979
+ listMcp,
2980
+ removeMcp,
2981
+ restartMcp,
2982
+ updateMcp
2983
+ } from "@wrongstack/mcp";
2933
2984
  function mapStatus(raw) {
2934
2985
  switch (raw) {
2935
2986
  case "connected":
@@ -3167,6 +3218,9 @@ async function handleMemoryForget(ws, msg, memoryStore) {
3167
3218
  sendResult(ws, false, errMessage(err));
3168
3219
  }
3169
3220
  }
3221
+
3222
+ // src/server/open-browser.ts
3223
+ import { spawn } from "node:child_process";
3170
3224
  function browserOpenCommand(url, platform = process.platform) {
3171
3225
  if (platform === "win32") {
3172
3226
  return { command: "cmd", args: ["/c", "start", "", url] };
@@ -3185,7 +3239,7 @@ function openBrowser(url, platform = process.platform) {
3185
3239
  child.unref();
3186
3240
  if (child.pid) {
3187
3241
  try {
3188
- import('@wrongstack/tools').then(({ getProcessRegistry }) => {
3242
+ import("@wrongstack/tools").then(({ getProcessRegistry }) => {
3189
3243
  const pid = child.pid;
3190
3244
  if (pid === void 0) return;
3191
3245
  getProcessRegistry().register({
@@ -3207,6 +3261,10 @@ function openBrowser(url, platform = process.platform) {
3207
3261
  } catch {
3208
3262
  }
3209
3263
  }
3264
+
3265
+ // src/server/port-utils.ts
3266
+ import * as net from "node:net";
3267
+ import { ToolValidationError as ToolValidationError3 } from "@wrongstack/core";
3210
3268
  function isPortFree(host, port) {
3211
3269
  return new Promise((resolve10) => {
3212
3270
  const srv = net.createServer();
@@ -3232,7 +3290,7 @@ async function findFreePort(host, startPort, opts = {}) {
3232
3290
  }
3233
3291
  port++;
3234
3292
  }
3235
- throw new ToolValidationError({
3293
+ throw new ToolValidationError3({
3236
3294
  message: `No free port found near ${startPort} on ${host} after ${maxTries} attempts.`,
3237
3295
  field: "port"
3238
3296
  });
@@ -3442,10 +3500,19 @@ async function handlePromptsRecent(ws, ctx) {
3442
3500
  send(ws, { type: "prompts.recent", payload: { slugs: [], error: errMessage(err) } });
3443
3501
  }
3444
3502
  }
3503
+
3504
+ // src/server/provider-config-standalone.ts
3505
+ import * as path8 from "node:path";
3506
+ import { DefaultSecretVault } from "@wrongstack/core";
3507
+
3508
+ // src/server/provider-config-io.ts
3509
+ import * as fs7 from "node:fs/promises";
3510
+ import { ConfigError, atomicWrite as atomicWrite4 } from "@wrongstack/core";
3511
+ import { decryptConfigSecrets, encryptConfigSecrets } from "@wrongstack/core/security";
3445
3512
  async function loadSavedProviders(configPath, vault) {
3446
3513
  let raw;
3447
3514
  try {
3448
- raw = await fs4.readFile(configPath, "utf8");
3515
+ raw = await fs7.readFile(configPath, "utf8");
3449
3516
  } catch {
3450
3517
  return {};
3451
3518
  }
@@ -3462,7 +3529,7 @@ async function saveProviders(configPath, vault, providers) {
3462
3529
  let raw;
3463
3530
  let fileExists = true;
3464
3531
  try {
3465
- raw = await fs4.readFile(configPath, "utf8");
3532
+ raw = await fs7.readFile(configPath, "utf8");
3466
3533
  } catch (err) {
3467
3534
  if (err.code !== "ENOENT") {
3468
3535
  throw new ConfigError({
@@ -3491,16 +3558,21 @@ async function saveProviders(configPath, vault, providers) {
3491
3558
  }
3492
3559
  parsed.providers = providers;
3493
3560
  const encrypted = encryptConfigSecrets(parsed, vault);
3494
- await atomicWrite(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
3561
+ await atomicWrite4(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
3495
3562
  }
3563
+
3564
+ // src/server/provider-config-standalone.ts
3496
3565
  function createProviderConfigIO(configPath) {
3497
- const keyFile = path5.join(path5.dirname(configPath), ".key");
3566
+ const keyFile = path8.join(path8.dirname(configPath), ".key");
3498
3567
  const vault = new DefaultSecretVault({ keyFile });
3499
3568
  return {
3500
3569
  load: () => loadSavedProviders(configPath, vault),
3501
3570
  save: (providers) => saveProviders(configPath, vault, providers)
3502
3571
  };
3503
3572
  }
3573
+
3574
+ // src/server/provider-keys.ts
3575
+ import { expectDefined } from "@wrongstack/core";
3504
3576
  function normalizeKeys(cfg) {
3505
3577
  if (Array.isArray(cfg.apiKeys) && cfg.apiKeys.length > 0) {
3506
3578
  return cfg.apiKeys.map((k) => ({ ...k }));
@@ -3594,6 +3666,12 @@ function removeProvider(providers, providerId) {
3594
3666
  delete providers[providerId];
3595
3667
  return { ok: true, message: `Provider "${providerId}" removed` };
3596
3668
  }
3669
+
3670
+ // src/server/sdd-board-ws-handler.ts
3671
+ import {
3672
+ applySddLifecycle,
3673
+ SddBoardStore
3674
+ } from "@wrongstack/sdd";
3597
3675
  var CONTROL_TYPES = /* @__PURE__ */ new Set([
3598
3676
  "pause",
3599
3677
  "resume",
@@ -3738,6 +3816,26 @@ var SddBoardWebSocketHandler = class {
3738
3816
  if (client.ws.readyState === 1) client.ws.send(JSON.stringify(msg));
3739
3817
  }
3740
3818
  };
3819
+
3820
+ // src/server/sdd-wizard-wiring.ts
3821
+ import * as path9 from "node:path";
3822
+ import { spawnSync as spawnSync2 } from "node:child_process";
3823
+ import {
3824
+ WorktreeManager as WorktreeManager2,
3825
+ ToolValidationError as ToolValidationError4
3826
+ } from "@wrongstack/core";
3827
+ import {
3828
+ cleanupStaleSddWorktrees,
3829
+ makeCommandVerifier,
3830
+ makeLlmSubtaskGenerator,
3831
+ SddBoardStore as SddBoardStore2,
3832
+ SddInterviewDriver,
3833
+ SddRunRegistry,
3834
+ SddSupervisor,
3835
+ SpecStore,
3836
+ startSddRun,
3837
+ TaskGraphStore
3838
+ } from "@wrongstack/sdd";
3741
3839
  var PLANNING_ONLY_GUARD = "SYSTEM: You are running a PLANNING-ONLY specification interview. Do NOT write, create, or edit any files, and do NOT run shell/terminal commands or use any code-editing tools \u2014 they are disabled here and any attempt will fail and waste the turn. Respond with TEXT ONLY: ask your question, or emit the requested spec / plan / task JSON. All code is written later, automatically, once the plan is approved and the multi-agent run starts.\n\n---\n\n";
3742
3840
  function buildSddWizardDeps(opts) {
3743
3841
  const registry = new SddRunRegistry();
@@ -3761,14 +3859,14 @@ function buildSddWizardDeps(opts) {
3761
3859
  makeDriver: () => new SddInterviewDriver({
3762
3860
  specStore: new SpecStore({ baseDir: opts.paths.projectSpecs }),
3763
3861
  graphStore: new TaskGraphStore({ baseDir: opts.paths.projectTaskGraphs }),
3764
- sessionPath: path5.join(opts.paths.projectDir, "sdd-wizard-session.json")
3862
+ sessionPath: path9.join(opts.paths.projectDir, "sdd-wizard-session.json")
3765
3863
  }),
3766
3864
  runInterviewTurn: (prompt) => runIsolatedTurn(prompt, "Spec Architect"),
3767
3865
  startRun: async (driver, { parallelSlots, defaultModel, defaultProvider, fallbackModels, worktrees: useWorktrees }) => {
3768
3866
  const graph = driver.getGraph();
3769
3867
  const tracker = driver.getTracker();
3770
3868
  if (!graph || !tracker) {
3771
- throw new ToolValidationError({
3869
+ throw new ToolValidationError4({
3772
3870
  message: "No task graph to run \u2014 finish the interview first.",
3773
3871
  field: "taskGraph"
3774
3872
  });
@@ -3776,7 +3874,7 @@ function buildSddWizardDeps(opts) {
3776
3874
  const worktreesEnabled = useWorktrees ?? process.env["WRONGSTACK_SDD_WORKTREES"] !== "0";
3777
3875
  let worktrees;
3778
3876
  if (worktreesEnabled) {
3779
- const inGit = spawnSync("git", ["rev-parse", "--is-inside-work-tree"], {
3877
+ const inGit = spawnSync2("git", ["rev-parse", "--is-inside-work-tree"], {
3780
3878
  cwd: opts.projectRoot,
3781
3879
  encoding: "utf8",
3782
3880
  windowsHide: true
@@ -3786,14 +3884,14 @@ function buildSddWizardDeps(opts) {
3786
3884
  projectRoot: opts.projectRoot,
3787
3885
  boardsDir: opts.paths.projectSddBoards
3788
3886
  }).catch(() => void 0);
3789
- worktrees = new WorktreeManager({
3887
+ worktrees = new WorktreeManager2({
3790
3888
  projectRoot: opts.projectRoot,
3791
3889
  events: opts.events,
3792
3890
  sessionId: () => opts.agent.ctx.session?.id
3793
3891
  });
3794
3892
  }
3795
3893
  }
3796
- const boardStore = new SddBoardStore({ baseDir: opts.paths.projectSddBoards });
3894
+ const boardStore = new SddBoardStore2({ baseDir: opts.paths.projectSddBoards });
3797
3895
  const verifyTask = makeCommandVerifier();
3798
3896
  const superviseFailure = opts.brain ? new SddSupervisor({
3799
3897
  brain: opts.brain,
@@ -3973,20 +4071,25 @@ var SddWizardWebSocketHandler = class {
3973
4071
  if (client.ws.readyState === 1) client.ws.send(JSON.stringify(msg));
3974
4072
  }
3975
4073
  };
4074
+
4075
+ // src/server/shell-open.ts
4076
+ import * as fs8 from "node:fs/promises";
4077
+ import * as path10 from "node:path";
4078
+ import { spawn as spawn2 } from "node:child_process";
3976
4079
  var METACHAR_REGEX = /[&|<>^"'`'\n\r]/;
3977
4080
  function shellQuote(s) {
3978
4081
  return s.replaceAll("'", `'"'"'`);
3979
4082
  }
3980
4083
  async function handleShellOpen(req, logger) {
3981
4084
  try {
3982
- const resolved = path5.resolve(req.path);
3983
- await fs4.access(resolved);
4085
+ const resolved = path10.resolve(req.path);
4086
+ await fs8.access(resolved);
3984
4087
  if (METACHAR_REGEX.test(resolved)) {
3985
4088
  return { success: false, message: "Path contains unsupported characters." };
3986
4089
  }
3987
4090
  const platform = process.platform;
3988
4091
  const launch = (cmd, args, onError) => {
3989
- const child = spawn(cmd, args, {
4092
+ const child = spawn2(cmd, args, {
3990
4093
  detached: true,
3991
4094
  stdio: "ignore",
3992
4095
  windowsHide: true
@@ -4030,6 +4133,12 @@ async function handleShellOpen(req, logger) {
4030
4133
  }
4031
4134
  }
4032
4135
 
4136
+ // src/server/skills-handlers.ts
4137
+ import { promises as fs9 } from "node:fs";
4138
+ import path11 from "node:path";
4139
+ import { atomicWrite as atomicWrite5 } from "@wrongstack/core";
4140
+ import { wstackGlobalRoot } from "@wrongstack/core/utils";
4141
+
4033
4142
  // src/server/ws-payload-validation.ts
4034
4143
  function isRecord(value) {
4035
4144
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -4624,6 +4733,123 @@ function validateProjectsSelectPayload(payload) {
4624
4733
  };
4625
4734
  }
4626
4735
 
4736
+ // src/server/zip.ts
4737
+ import { deflateRawSync, inflateRawSync } from "node:zlib";
4738
+ function createZipBuffer(entries) {
4739
+ const localParts = [];
4740
+ const centralParts = [];
4741
+ let offset = 0;
4742
+ const { date, time } = dosDateTime(/* @__PURE__ */ new Date());
4743
+ for (const entry of entries) {
4744
+ const name2 = Buffer.from(normalizeZipPath(entry.name), "utf8");
4745
+ const data = typeof entry.data === "string" ? Buffer.from(entry.data, "utf8") : Buffer.from(entry.data);
4746
+ const compressed = deflateRawSync(data);
4747
+ const crc = crc32(data);
4748
+ const local = Buffer.alloc(30);
4749
+ local.writeUInt32LE(67324752, 0);
4750
+ local.writeUInt16LE(20, 4);
4751
+ local.writeUInt16LE(2048, 6);
4752
+ local.writeUInt16LE(8, 8);
4753
+ local.writeUInt16LE(time, 10);
4754
+ local.writeUInt16LE(date, 12);
4755
+ local.writeUInt32LE(crc, 14);
4756
+ local.writeUInt32LE(compressed.length, 18);
4757
+ local.writeUInt32LE(data.length, 22);
4758
+ local.writeUInt16LE(name2.length, 26);
4759
+ localParts.push(local, name2, compressed);
4760
+ const central = Buffer.alloc(46);
4761
+ central.writeUInt32LE(33639248, 0);
4762
+ central.writeUInt16LE(798, 4);
4763
+ central.writeUInt16LE(20, 6);
4764
+ central.writeUInt16LE(2048, 8);
4765
+ central.writeUInt16LE(8, 10);
4766
+ central.writeUInt16LE(time, 12);
4767
+ central.writeUInt16LE(date, 14);
4768
+ central.writeUInt32LE(crc, 16);
4769
+ central.writeUInt32LE(compressed.length, 20);
4770
+ central.writeUInt32LE(data.length, 24);
4771
+ central.writeUInt16LE(name2.length, 28);
4772
+ central.writeUInt32LE(offset, 42);
4773
+ centralParts.push(central, name2);
4774
+ offset += local.length + name2.length + compressed.length;
4775
+ }
4776
+ const centralDirectory = Buffer.concat(centralParts);
4777
+ const end = Buffer.alloc(22);
4778
+ end.writeUInt32LE(101010256, 0);
4779
+ end.writeUInt16LE(entries.length, 8);
4780
+ end.writeUInt16LE(entries.length, 10);
4781
+ end.writeUInt32LE(centralDirectory.length, 12);
4782
+ end.writeUInt32LE(offset, 16);
4783
+ return Buffer.concat([...localParts, centralDirectory, end]);
4784
+ }
4785
+ function readZipEntries(archive) {
4786
+ const maxEntries = 1e3;
4787
+ const maxEntryBytes = 64 * 1024 * 1024;
4788
+ const maxTotalBytes = 128 * 1024 * 1024;
4789
+ const buffer = Buffer.from(archive);
4790
+ const result = /* @__PURE__ */ new Map();
4791
+ let totalBytes = 0;
4792
+ let offset = 0;
4793
+ while (offset + 4 <= buffer.length && buffer.readUInt32LE(offset) === 67324752) {
4794
+ if (offset + 30 > buffer.length) throw new Error("Truncated ZIP local header.");
4795
+ const flags = buffer.readUInt16LE(offset + 6);
4796
+ const method = buffer.readUInt16LE(offset + 8);
4797
+ if ((flags & 1) !== 0) throw new Error("Encrypted ZIP entries are not supported.");
4798
+ if ((flags & 8) !== 0) throw new Error("ZIP data descriptors are not supported.");
4799
+ const compressedSize = buffer.readUInt32LE(offset + 18);
4800
+ const expectedSize = buffer.readUInt32LE(offset + 22);
4801
+ if (result.size >= maxEntries) throw new Error("ZIP contains too many entries.");
4802
+ if (expectedSize > maxEntryBytes || totalBytes + expectedSize > maxTotalBytes) {
4803
+ throw new Error("ZIP expands beyond the configured size limit.");
4804
+ }
4805
+ if (compressedSize > 0 && expectedSize / compressedSize > 1e3) {
4806
+ throw new Error("ZIP entry has a suspicious compression ratio.");
4807
+ }
4808
+ const nameLength = buffer.readUInt16LE(offset + 26);
4809
+ const extraLength = buffer.readUInt16LE(offset + 28);
4810
+ const nameStart = offset + 30;
4811
+ const dataStart = nameStart + nameLength + extraLength;
4812
+ const dataEnd = dataStart + compressedSize;
4813
+ if (dataEnd > buffer.length) throw new Error("Truncated ZIP entry.");
4814
+ const name2 = buffer.subarray(nameStart, nameStart + nameLength).toString("utf8");
4815
+ if (!isSafeZipPath(name2)) throw new Error(`Unsafe ZIP entry path: ${name2}`);
4816
+ const compressed = buffer.subarray(dataStart, dataEnd);
4817
+ const data = method === 0 ? Buffer.from(compressed) : method === 8 ? inflateRawSync(compressed) : void 0;
4818
+ if (!data) throw new Error(`Unsupported ZIP compression method: ${method}`);
4819
+ if (data.length !== expectedSize) throw new Error(`ZIP size mismatch for ${name2}`);
4820
+ if (crc32(data) !== buffer.readUInt32LE(offset + 14)) throw new Error(`ZIP CRC mismatch for ${name2}`);
4821
+ result.set(name2, data);
4822
+ totalBytes += data.length;
4823
+ offset = dataEnd;
4824
+ }
4825
+ return result;
4826
+ }
4827
+ function normalizeZipPath(value) {
4828
+ const normalized = value.replace(/\\/g, "/").replace(/^\/+/, "");
4829
+ if (!isSafeZipPath(normalized)) throw new Error(`Unsafe ZIP entry path: ${value}`);
4830
+ return normalized;
4831
+ }
4832
+ function isSafeZipPath(value) {
4833
+ return value.length > 0 && !value.includes("\0") && !value.startsWith("/") && !/^[a-z]:/i.test(value) && !value.split("/").includes("..");
4834
+ }
4835
+ function dosDateTime(value) {
4836
+ const year = Math.max(1980, Math.min(2107, value.getFullYear()));
4837
+ return {
4838
+ date: year - 1980 << 9 | value.getMonth() + 1 << 5 | value.getDate(),
4839
+ time: value.getHours() << 11 | value.getMinutes() << 5 | Math.floor(value.getSeconds() / 2)
4840
+ };
4841
+ }
4842
+ var CRC_TABLE = Array.from({ length: 256 }, (_, index) => {
4843
+ let crc = index;
4844
+ for (let bit = 0; bit < 8; bit++) crc = (crc & 1) !== 0 ? 3988292384 ^ crc >>> 1 : crc >>> 1;
4845
+ return crc >>> 0;
4846
+ });
4847
+ function crc32(data) {
4848
+ let crc = 4294967295;
4849
+ for (const byte of data) crc = crc >>> 8 ^ (CRC_TABLE[(crc ^ byte) & 255] ?? 0);
4850
+ return (crc ^ 4294967295) >>> 0;
4851
+ }
4852
+
4627
4853
  // src/server/skills-handlers.ts
4628
4854
  async function handleSkillsList(ws, ctx) {
4629
4855
  if (!ctx.skillLoader) {
@@ -4692,19 +4918,19 @@ async function handleSkillsContent(ws, ctx, msg) {
4692
4918
  send(ws, { type: "skills.content", payload: { name: name2, body: "", path: "", source, relatedFiles: [], references: [], error: `Skill "${name2}" not found` } });
4693
4919
  return;
4694
4920
  }
4695
- const body = await promises.readFile(entry.path, "utf8");
4696
- const skillDir = path5__default.dirname(entry.path);
4921
+ const body = await fs9.readFile(entry.path, "utf8");
4922
+ const skillDir = path11.dirname(entry.path);
4697
4923
  let relatedFiles = [];
4698
4924
  try {
4699
- const files = await promises.readdir(skillDir);
4700
- relatedFiles = files.filter((f) => f !== path5__default.basename(entry.path)).map((f) => path5__default.join(skillDir, f));
4925
+ const files = await fs9.readdir(skillDir);
4926
+ relatedFiles = files.filter((f) => f !== path11.basename(entry.path)).map((f) => path11.join(skillDir, f));
4701
4927
  } catch {
4702
4928
  }
4703
4929
  const nameLower = name2.toLowerCase();
4704
4930
  const refResults = await Promise.all(
4705
4931
  entries.filter((e) => e.name.toLowerCase() !== nameLower).map(async (e) => {
4706
4932
  try {
4707
- const content = await promises.readFile(e.path, "utf8");
4933
+ const content = await fs9.readFile(e.path, "utf8");
4708
4934
  return [e.name, content.toLowerCase().includes(nameLower)];
4709
4935
  } catch {
4710
4936
  return [e.name, false];
@@ -4794,20 +5020,20 @@ async function handleSkillsCreate(ws, ctx, msg) {
4794
5020
  }
4795
5021
  const createPayload = parsed.value;
4796
5022
  try {
4797
- const targetDir = createPayload.scope === "global" ? path5__default.join(
4798
- ctx.globalSkillsDir ?? path5__default.join(wstackGlobalRoot(), "skills"),
5023
+ const targetDir = createPayload.scope === "global" ? path11.join(
5024
+ ctx.globalSkillsDir ?? path11.join(wstackGlobalRoot(), "skills"),
4799
5025
  createPayload.name.trim()
4800
- ) : path5__default.join(
4801
- ctx.projectSkillsDir ?? path5__default.join(ctx.projectRoot, ".wrongstack", "skills"),
5026
+ ) : path11.join(
5027
+ ctx.projectSkillsDir ?? path11.join(ctx.projectRoot, ".wrongstack", "skills"),
4802
5028
  createPayload.name.trim()
4803
5029
  );
4804
5030
  try {
4805
- await promises.access(targetDir);
5031
+ await fs9.access(targetDir);
4806
5032
  send(ws, { type: "skills.created", payload: { success: false, error: `Skill "${createPayload.name}" already exists` } });
4807
5033
  return;
4808
5034
  } catch {
4809
5035
  }
4810
- await promises.mkdir(targetDir, { recursive: true });
5036
+ await fs9.mkdir(targetDir, { recursive: true });
4811
5037
  const lines = createPayload.description.trim().split("\n");
4812
5038
  const firstLine = (lines[0] ?? "").trim();
4813
5039
  const bodyLines = lines.slice(1).map((l) => l.trim()).filter(Boolean);
@@ -4855,13 +5081,13 @@ ${trigger}
4855
5081
  "- `bug-hunter` \u2014 for systematic bug detection patterns",
4856
5082
  "- `output-standards` \u2014 for standardized `<nextsteps>` formatting"
4857
5083
  ].join("\n");
4858
- await atomicWrite(path5__default.join(targetDir, "SKILL.md"), skillContent);
5084
+ await atomicWrite5(path11.join(targetDir, "SKILL.md"), skillContent);
4859
5085
  send(ws, {
4860
5086
  type: "skills.created",
4861
5087
  payload: {
4862
5088
  success: true,
4863
5089
  error: null,
4864
- skill: { name: createPayload.name.trim(), path: path5__default.join(targetDir, "SKILL.md"), scope: createPayload.scope }
5090
+ skill: { name: createPayload.name.trim(), path: path11.join(targetDir, "SKILL.md"), scope: createPayload.scope }
4865
5091
  }
4866
5092
  });
4867
5093
  } catch (err) {
@@ -4891,7 +5117,7 @@ async function handleSkillsEdit(ws, ctx, msg) {
4891
5117
  send(ws, { type: "skills.edited", payload: { success: false, error: `${label} skills cannot be edited` } });
4892
5118
  return;
4893
5119
  }
4894
- await atomicWrite(entry.path, editPayload.body);
5120
+ await atomicWrite5(entry.path, editPayload.body);
4895
5121
  send(ws, { type: "skills.edited", payload: { success: true, error: null } });
4896
5122
  } catch (err) {
4897
5123
  send(ws, { type: "skills.edited", payload: { success: false, error: errMessage(err) } });
@@ -4904,29 +5130,35 @@ async function handleSkillsExport(ws, ctx) {
4904
5130
  }
4905
5131
  try {
4906
5132
  const entries = await ctx.skillLoader.listEntries();
4907
- const zip = new JSZip();
5133
+ const zipEntries = [];
4908
5134
  for (const entry of entries) {
4909
5135
  try {
4910
5136
  const body = await ctx.skillLoader.readBody(entry.name);
4911
5137
  const safeName = entry.name.replace(/\//g, "_");
4912
- zip.file(`${safeName}/SKILL.md`, body);
5138
+ zipEntries.push({ name: `${safeName}/SKILL.md`, data: body });
4913
5139
  } catch {
4914
5140
  }
4915
5141
  }
4916
- const zipBuffer = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
5142
+ const zipBuffer = createZipBuffer(zipEntries);
4917
5143
  const zipBase64 = zipBuffer.toString("base64");
4918
5144
  send(ws, { type: "skills.exported", payload: { zipBase64, skillCount: entries.length, error: void 0 } });
4919
5145
  } catch (err) {
4920
5146
  send(ws, { type: "skills.exported", payload: { zipBase64: "", skillCount: 0, error: errMessage(err) } });
4921
5147
  }
4922
5148
  }
5149
+
5150
+ // src/server/specs-ws-handler.ts
5151
+ import {
5152
+ computeTaskProgress
5153
+ } from "@wrongstack/core";
5154
+ import { SpecStore as SpecStore2, TaskGraphStore as TaskGraphStore2 } from "@wrongstack/sdd";
4923
5155
  var SpecsWebSocketHandler = class {
4924
5156
  specStore;
4925
5157
  graphStore;
4926
5158
  clients = /* @__PURE__ */ new Set();
4927
5159
  constructor(specsDir, taskGraphsDir) {
4928
- this.specStore = new SpecStore({ baseDir: specsDir });
4929
- this.graphStore = new TaskGraphStore({ baseDir: taskGraphsDir });
5160
+ this.specStore = new SpecStore2({ baseDir: specsDir });
5161
+ this.graphStore = new TaskGraphStore2({ baseDir: taskGraphsDir });
4930
5162
  }
4931
5163
  addClient(ws) {
4932
5164
  const client = { ws, id: crypto.randomUUID() };
@@ -5130,6 +5362,13 @@ function estimateContextBreakdown(input) {
5130
5362
  messages: { total: msgTokens, count: input.messages.length, breakdown: messageBreakdown }
5131
5363
  };
5132
5364
  }
5365
+
5366
+ // src/server/worktree-ws-handler.ts
5367
+ import { join as join8, resolve as resolve6, sep as sep3 } from "node:path";
5368
+ import { WorktreeManager as WorktreeManager3 } from "@wrongstack/core";
5369
+ import { cleanupStaleSddWorktrees as cleanupStaleSddWorktrees2 } from "@wrongstack/sdd";
5370
+ import { toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
5371
+ var MAX_ACTIVITY = 6;
5133
5372
  var ACTIVE_STATUSES = /* @__PURE__ */ new Set(["allocating", "active", "committing", "merging"]);
5134
5373
  var MANAGED_BRANCH_RE = /^wstack\/ap\/[A-Za-z0-9._/-]+$/;
5135
5374
  var WorktreeWebSocketHandler = class {
@@ -5186,13 +5425,13 @@ var WorktreeWebSocketHandler = class {
5186
5425
  // ── orphan management ─────────────────────────────────────────────────────
5187
5426
  /** Absolute managed-worktrees root for this project. */
5188
5427
  worktreesRoot() {
5189
- return resolve(join(this.management.projectRoot, ".wrongstack", "worktrees"));
5428
+ return resolve6(join8(this.management.projectRoot, ".wrongstack", "worktrees"));
5190
5429
  }
5191
5430
  /** True iff `dir` resolves strictly inside the managed worktrees root. */
5192
5431
  underRoot(dir) {
5193
- const abs = resolve(dir);
5432
+ const abs = resolve6(dir);
5194
5433
  const root = this.worktreesRoot();
5195
- return abs !== root && abs.startsWith(root + sep);
5434
+ return abs !== root && abs.startsWith(root + sep3);
5196
5435
  }
5197
5436
  /** Branches of worktrees a live in-session run currently owns. */
5198
5437
  liveActiveBranches() {
@@ -5213,7 +5452,7 @@ var WorktreeWebSocketHandler = class {
5213
5452
  return;
5214
5453
  }
5215
5454
  try {
5216
- const wt = new WorktreeManager({ projectRoot: this.management.projectRoot });
5455
+ const wt = new WorktreeManager3({ projectRoot: this.management.projectRoot });
5217
5456
  const { worktrees, branches } = await wt.listManaged();
5218
5457
  const live = this.liveActiveBranches();
5219
5458
  const orphans = [];
@@ -5237,7 +5476,7 @@ var WorktreeWebSocketHandler = class {
5237
5476
  }
5238
5477
  });
5239
5478
  } catch (err) {
5240
- this.logger.debug?.(`worktree orphan scan failed: ${toErrorMessage(err)}`);
5479
+ this.logger.debug?.(`worktree orphan scan failed: ${toErrorMessage2(err)}`);
5241
5480
  this.broadcast({ type: "worktree.orphans", payload: { orphans: [], canClean: false } });
5242
5481
  }
5243
5482
  }
@@ -5261,7 +5500,7 @@ var WorktreeWebSocketHandler = class {
5261
5500
  });
5262
5501
  return;
5263
5502
  }
5264
- const res = await cleanupStaleSddWorktrees({
5503
+ const res = await cleanupStaleSddWorktrees2({
5265
5504
  projectRoot: this.management.projectRoot,
5266
5505
  boardsDir: this.management.boardsDir
5267
5506
  });
@@ -5300,7 +5539,7 @@ var WorktreeWebSocketHandler = class {
5300
5539
  }
5301
5540
  let removed = false;
5302
5541
  if (dir) {
5303
- const wt = new WorktreeManager({ projectRoot: this.management.projectRoot });
5542
+ const wt = new WorktreeManager3({ projectRoot: this.management.projectRoot });
5304
5543
  ({ removed } = await wt.removeOne(dir, branch));
5305
5544
  }
5306
5545
  for (const [id, h] of [...this.handles]) {
@@ -5324,7 +5563,7 @@ var WorktreeWebSocketHandler = class {
5324
5563
  this.broadcast({ type: "worktree.merge_result", payload: { ok: false, branch, reason: "a run is live on this worktree \u2014 stop it first" } });
5325
5564
  return;
5326
5565
  }
5327
- const wt = new WorktreeManager({ projectRoot: this.management.projectRoot });
5566
+ const wt = new WorktreeManager3({ projectRoot: this.management.projectRoot });
5328
5567
  const res = await wt.mergeBranch(branch);
5329
5568
  this.broadcast({
5330
5569
  type: "worktree.merge_result",
@@ -5339,8 +5578,8 @@ var WorktreeWebSocketHandler = class {
5339
5578
  return;
5340
5579
  }
5341
5580
  const base = baseBranch && MANAGED_BRANCH_RE.test(baseBranch) ? baseBranch : void 0;
5342
- const wt = new WorktreeManager({ projectRoot: this.management.projectRoot });
5343
- const summary = await wt.diffSummary(resolve(dir), base);
5581
+ const wt = new WorktreeManager3({ projectRoot: this.management.projectRoot });
5582
+ const summary = await wt.diffSummary(resolve6(dir), base);
5344
5583
  this.broadcast({ type: "worktree.diff_result", payload: { dir, summary } });
5345
5584
  }
5346
5585
  // ── internals ───────────────────────────────────────────────────────────
@@ -5412,7 +5651,7 @@ var WorktreeWebSocketHandler = class {
5412
5651
  activity(id, kind, text) {
5413
5652
  const cur = this.handles.get(id);
5414
5653
  if (cur) {
5415
- const recentActivity = [...cur.recentActivity, { kind, text, at: Date.now() }].slice(-6);
5654
+ const recentActivity = [...cur.recentActivity, { kind, text, at: Date.now() }].slice(-MAX_ACTIVITY);
5416
5655
  this.handles.set(id, { ...cur, recentActivity });
5417
5656
  }
5418
5657
  this.broadcast({ type: "worktree.event", payload: { kind, handleId: id, text, at: Date.now() } });
@@ -5444,7 +5683,7 @@ var WorktreeWebSocketHandler = class {
5444
5683
  try {
5445
5684
  if (ws.readyState === 1) ws.send(data);
5446
5685
  } catch (err) {
5447
- this.logger.debug?.(`worktree broadcast failed: ${toErrorMessage(err)}`);
5686
+ this.logger.debug?.(`worktree broadcast failed: ${toErrorMessage2(err)}`);
5448
5687
  }
5449
5688
  }
5450
5689
  }
@@ -5456,6 +5695,12 @@ var WorktreeWebSocketHandler = class {
5456
5695
  }
5457
5696
  };
5458
5697
 
5698
+ // src/server/server-runtime.ts
5699
+ import * as path13 from "node:path";
5700
+ import { createRequire } from "node:module";
5701
+ import { fileURLToPath } from "node:url";
5702
+ import { WebSocketServer } from "ws";
5703
+
5459
5704
  // src/server/lifecycle.ts
5460
5705
  function createShutdown(res) {
5461
5706
  const log = res.log ?? ((m) => console.log(m));
@@ -5491,9 +5736,14 @@ function registerShutdownHandlers(res) {
5491
5736
  process.off("SIGTERM", shutdown);
5492
5737
  };
5493
5738
  }
5739
+
5740
+ // src/server/setup-events.ts
5741
+ import * as fs10 from "node:fs/promises";
5742
+ import { watch as fsWatch } from "node:fs";
5743
+ import * as path12 from "node:path";
5494
5744
  function statusProjectHashFromWatchFilename(projectsDir, filename) {
5495
5745
  const raw = String(filename);
5496
- const relative4 = path5.isAbsolute(raw) ? path5.relative(projectsDir, raw) : raw;
5746
+ const relative4 = path12.isAbsolute(raw) ? path12.relative(projectsDir, raw) : raw;
5497
5747
  const parts = relative4.split(/[\\/]+/).filter(Boolean);
5498
5748
  if (parts.length < 2) return null;
5499
5749
  if (parts[parts.length - 1] !== "status.json") return null;
@@ -5630,7 +5880,7 @@ function setupEvents(deps2) {
5630
5880
  try {
5631
5881
  const taskPath = context.meta["task.path"];
5632
5882
  if (typeof taskPath === "string" && taskPath) {
5633
- const { loadTasks } = await import('@wrongstack/core');
5883
+ const { loadTasks } = await import("@wrongstack/core");
5634
5884
  const file = await loadTasks(taskPath);
5635
5885
  broadcast2(clients, { type: "tasks.updated", payload: sessionPayload2({ sessionId: e.sessionId, tasks: file?.tasks ?? [] }) });
5636
5886
  }
@@ -5639,7 +5889,7 @@ function setupEvents(deps2) {
5639
5889
  try {
5640
5890
  const planPath = context.meta["plan.path"];
5641
5891
  if (typeof planPath === "string" && planPath) {
5642
- const { loadPlan } = await import('@wrongstack/core');
5892
+ const { loadPlan } = await import("@wrongstack/core");
5643
5893
  const plan = await loadPlan(planPath);
5644
5894
  broadcast2(clients, { type: "plan.updated", payload: sessionPayload2({ sessionId: e.sessionId, plan: plan ?? { version: 1, sessionId: e.sessionId ?? context.session?.id ?? "", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), items: [] } }) });
5645
5895
  }
@@ -5936,6 +6186,7 @@ function setupEvents(deps2) {
5936
6186
  events.on("subagent.budget_extended", (e) => forwardSubagent("budget_extended", { sessionId: e.sessionId, subagentId: e.subagentId, budgetKind: e.kind, newLimit: e.newLimit, totalExtensions: e.totalExtensions }));
5937
6187
  events.on("subagent.ctx_pct", (e) => forwardSubagent("ctx_pct", { sessionId: e.sessionId, subagentId: e.subagentId, load: e.load, tokens: e.tokens, maxContext: e.maxContext }));
5938
6188
  events.on("subagent.task_completed", (e) => forwardSubagent("task_completed", { sessionId: e.sessionId, subagentId: e.subagentId, status: e.status, iterations: e.iterations, toolCalls: e.toolCalls, finalText: e.finalText, failureReason: e.error?.kind, error: e.error ? { kind: e.error.kind, message: e.error.message } : void 0 }));
6189
+ events.on("subagent.removed", (e) => forwardSubagent("removed", { sessionId: e.sessionId, subagentId: e.subagentId, reason: e.reason }));
5939
6190
  events.on("agent.timeline.message", (e) => {
5940
6191
  broadcast2(clients, {
5941
6192
  type: "agent.timeline.message",
@@ -6033,14 +6284,20 @@ function setupEvents(deps2) {
6033
6284
  payload: sessionPayload2({ event: eventName, ...payload })
6034
6285
  });
6035
6286
  });
6287
+ events.onPattern("memory.*", (eventName, payload) => {
6288
+ broadcast2(clients, {
6289
+ type: "memory.event",
6290
+ payload: sessionPayload2({ event: eventName, ...payload })
6291
+ });
6292
+ });
6036
6293
  events.on("client.status", async (e) => {
6037
6294
  broadcast2(clients, { type: "client.status_update", payload: e });
6038
6295
  if (wpaths?.projectStatus) {
6039
6296
  try {
6040
6297
  const statusFile = wpaths.projectStatus(e.projectHash);
6041
- const dir = path5.dirname(statusFile);
6042
- await fs4.mkdir(dir, { recursive: true });
6043
- await fs4.writeFile(statusFile, JSON.stringify(e, null, 2), "utf-8");
6298
+ const dir = path12.dirname(statusFile);
6299
+ await fs10.mkdir(dir, { recursive: true });
6300
+ await fs10.writeFile(statusFile, JSON.stringify(e, null, 2), "utf-8");
6044
6301
  } catch (err) {
6045
6302
  console.error(
6046
6303
  JSON.stringify({
@@ -6054,7 +6311,7 @@ function setupEvents(deps2) {
6054
6311
  }
6055
6312
  });
6056
6313
  if (wpaths?.projectStatus && wpaths.configDir) {
6057
- const projectsDir = path5.join(wpaths.configDir, "projects");
6314
+ const projectsDir = path12.join(wpaths.configDir, "projects");
6058
6315
  const knownProjectHashes = /* @__PURE__ */ new Set();
6059
6316
  const debounceTimers = /* @__PURE__ */ new Map();
6060
6317
  const DEBOUNCE_MS = 150;
@@ -6118,8 +6375,8 @@ function setupEvents(deps2) {
6118
6375
  let watcher;
6119
6376
  const startWatcher = async () => {
6120
6377
  try {
6121
- await fs4.mkdir(projectsDir, { recursive: true });
6122
- watcher = watch(projectsDir, { persistent: true, recursive: true }, async (eventType, filename) => {
6378
+ await fs10.mkdir(projectsDir, { recursive: true });
6379
+ watcher = fsWatch(projectsDir, { persistent: true, recursive: true }, async (eventType, filename) => {
6123
6380
  if (eventType !== "change" && eventType !== "rename") return;
6124
6381
  if (filename == null) return;
6125
6382
  const projectHash = statusProjectHashFromWatchFilename(projectsDir, filename);
@@ -6128,8 +6385,8 @@ function setupEvents(deps2) {
6128
6385
  if (!knownProjectHashes.has(projectHash)) return;
6129
6386
  if (watcherMetrics) watcherMetrics.filesProcessed++;
6130
6387
  try {
6131
- const targetFile = path5.join(projectsDir, projectHash, "status.json");
6132
- const content = await fs4.readFile(targetFile, "utf-8");
6388
+ const targetFile = path12.join(projectsDir, projectHash, "status.json");
6389
+ const content = await fs10.readFile(targetFile, "utf-8");
6133
6390
  const statusData = JSON.parse(content);
6134
6391
  scheduleBroadcast(projectHash, statusData);
6135
6392
  } catch {
@@ -6181,11 +6438,11 @@ function setupEvents(deps2) {
6181
6438
  }
6182
6439
  });
6183
6440
  }
6184
- const globalRoot = globalConfigPath ? path5.dirname(globalConfigPath) : void 0;
6441
+ const globalRoot = globalConfigPath ? path12.dirname(globalConfigPath) : void 0;
6185
6442
  if (globalRoot) {
6186
6443
  const broadcastSessions = async () => {
6187
6444
  try {
6188
- const { SessionRegistry } = await import('@wrongstack/core');
6445
+ const { SessionRegistry } = await import("@wrongstack/core");
6189
6446
  const registry = new SessionRegistry(globalRoot);
6190
6447
  const sessions = await registry.list();
6191
6448
  const mySlug = sessions.find((s) => s.pid === process.pid)?.projectSlug;
@@ -6228,7 +6485,7 @@ function setupEvents(deps2) {
6228
6485
  disposers.push(() => clearInterval(statusInterval));
6229
6486
  let regDebounce;
6230
6487
  try {
6231
- const regWatcher = watch(globalRoot, { persistent: false }, (_event, filename) => {
6488
+ const regWatcher = fsWatch(globalRoot, { persistent: false }, (_event, filename) => {
6232
6489
  const name2 = filename ? String(filename) : "";
6233
6490
  if (!name2.startsWith("session-registry.json") || name2.endsWith(".lock")) return;
6234
6491
  if (regDebounce) clearTimeout(regDebounce);
@@ -6264,6 +6521,9 @@ function getCostRates(model) {
6264
6521
  function computeUsageCost(usage, rates) {
6265
6522
  return (usage.input * rates.input + usage.output * rates.output + (usage.cacheRead ?? 0) * rates.cacheRead) / 1e6;
6266
6523
  }
6524
+
6525
+ // src/server/model-catalog.ts
6526
+ import { capabilitiesFor } from "@wrongstack/providers";
6267
6527
  var SIBLING_CATALOG = {
6268
6528
  "anthropic-oauth": "anthropic",
6269
6529
  "openai-codex": "openai",
@@ -6370,6 +6630,9 @@ function readConfiguredBool(providerConfig, key) {
6370
6630
  function positiveNumber(value) {
6371
6631
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
6372
6632
  }
6633
+
6634
+ // src/server/server-runtime.ts
6635
+ import { toErrorMessage as toErrorMessage3 } from "@wrongstack/core/utils";
6373
6636
  async function resolvePorts(opts) {
6374
6637
  const requestedWsPort = opts.wsPort ?? 3457;
6375
6638
  const wsHost = opts.wsHost ?? process.env["WEBUI_HOST"] ?? process.env["WS_HOST"] ?? "127.0.0.1";
@@ -6430,7 +6693,7 @@ function createSessionStartPayload(g) {
6430
6693
  inputCost,
6431
6694
  outputCost,
6432
6695
  cacheReadCost,
6433
- projectName: path5.basename(projectRoot) || projectRoot,
6696
+ projectName: path13.basename(projectRoot) || projectRoot,
6434
6697
  projectRoot,
6435
6698
  cwd: g.getWorkingDir(),
6436
6699
  mode: g.getModeId(),
@@ -6468,13 +6731,26 @@ function createWsServers(ports, accessToken) {
6468
6731
  port: ports.wsPort,
6469
6732
  host: ports.wsHost,
6470
6733
  verifyClient: verifyClient2,
6471
- maxPayload: WS_MAX_PAYLOAD
6734
+ maxPayload: WS_MAX_PAYLOAD,
6735
+ // Send a ping every 15s to keep idle connections alive. Without this,
6736
+ // network equipment (routers, proxies, NAT gateways) may drop idle TCP
6737
+ // connections, causing the browser to see a close event and show the
6738
+ // "reconnecting" banner. The browser responds with a pong automatically
6739
+ // (the WebSocket API handles this at the transport level).
6740
+ pingInterval: 15e3,
6741
+ // Wait 5s for a pong before considering the connection dead. A client
6742
+ // that hasn't responded to 3 consecutive pings in a row (45s total
6743
+ // quiet) is almost certainly unreachable — close the socket so the
6744
+ // client can reconnect cleanly rather than hanging indefinitely.
6745
+ pingTimeout: 5e3
6472
6746
  });
6473
6747
  const wssSecondary = ports.wsHost === "127.0.0.1" ? new WebSocketServer({
6474
6748
  port: ports.wsPort,
6475
6749
  host: "::1",
6476
6750
  verifyClient: verifyClient2,
6477
- maxPayload: WS_MAX_PAYLOAD
6751
+ maxPayload: WS_MAX_PAYLOAD,
6752
+ pingInterval: 15e3,
6753
+ pingTimeout: 5e3
6478
6754
  }) : null;
6479
6755
  const clients = /* @__PURE__ */ new Map();
6480
6756
  console.log(
@@ -6496,7 +6772,7 @@ function armEvents(wssPrimary, wssSecondary, wsHost, wsPort, setupInput, watcher
6496
6772
  };
6497
6773
  wssPrimary.on("listening", () => arm(`${wsHost}:${wsPort}`));
6498
6774
  wssPrimary.on("error", (err) => {
6499
- console.error(JSON.stringify({ level: "error", event: "webui.ws_server_error", host: wsHost, message: toErrorMessage(err), timestamp: (/* @__PURE__ */ new Date()).toISOString() }));
6775
+ console.error(JSON.stringify({ level: "error", event: "webui.ws_server_error", host: wsHost, message: toErrorMessage3(err), timestamp: (/* @__PURE__ */ new Date()).toISOString() }));
6500
6776
  });
6501
6777
  if (wssSecondary) {
6502
6778
  wssSecondary.on("listening", () => arm(`::1:${wsPort}`));
@@ -6515,13 +6791,13 @@ function armEvents(wssPrimary, wssSecondary, wsHost, wsPort, setupInput, watcher
6515
6791
  };
6516
6792
  }
6517
6793
  function resolveWebuiDistDir(fromUrl, explicitDistDir) {
6518
- if (explicitDistDir) return path5.resolve(explicitDistDir);
6794
+ if (explicitDistDir) return path13.resolve(explicitDistDir);
6519
6795
  try {
6520
6796
  const requireFromHere2 = createRequire(fromUrl);
6521
6797
  const serverEntry = requireFromHere2.resolve("@wrongstack/webui/server");
6522
- return path5.resolve(path5.dirname(serverEntry), "..");
6798
+ return path13.resolve(path13.dirname(serverEntry), "..");
6523
6799
  } catch {
6524
- return path5.resolve(path5.dirname(fileURLToPath(fromUrl)), "..", "..", "dist");
6800
+ return path13.resolve(path13.dirname(fileURLToPath(fromUrl)), "..", "..", "dist");
6525
6801
  }
6526
6802
  }
6527
6803
  function startHttpServer(opts) {
@@ -6536,13 +6812,13 @@ function startHttpServer(opts) {
6536
6812
  watcherMetrics: opts.watcherMetrics,
6537
6813
  onFleetPing: opts.onFleetPing
6538
6814
  });
6539
- const registryBaseDir = path5.dirname(opts.globalConfigPath);
6815
+ const registryBaseDir = path13.dirname(opts.globalConfigPath);
6540
6816
  httpServer.listen(opts.httpPort, opts.wsHost, () => {
6541
6817
  const openUrl = buildWebUIAccessUrl({ host: opts.wsHost, port: opts.httpPort, token: opts.wsToken, publicUrl: opts.publicUrl });
6542
6818
  console.log(`[WebUI] HTTP server running on ${openUrl}`);
6543
6819
  if (opts.openBrowser) openBrowser(openUrl);
6544
6820
  void registerInstance(
6545
- { pid: process.pid, httpPort: opts.httpPort, wsPort: opts.wsPort, host: opts.wsHost, projectRoot: opts.projectRoot, projectName: path5.basename(opts.projectRoot) || opts.projectRoot, startedAt: (/* @__PURE__ */ new Date()).toISOString(), url: buildWebUIAccessUrl({ host: opts.wsHost, port: opts.httpPort, publicUrl: opts.publicUrl }) },
6821
+ { pid: process.pid, httpPort: opts.httpPort, wsPort: opts.wsPort, host: opts.wsHost, projectRoot: opts.projectRoot, projectName: path13.basename(opts.projectRoot) || opts.projectRoot, startedAt: (/* @__PURE__ */ new Date()).toISOString(), url: buildWebUIAccessUrl({ host: opts.wsHost, port: opts.httpPort, publicUrl: opts.publicUrl }) },
6546
6822
  registryBaseDir
6547
6823
  ).catch((err) => console.warn(JSON.stringify({ level: "warn", event: "webui.instance_record_failed", message: errMessage(err), timestamp: (/* @__PURE__ */ new Date()).toISOString() })));
6548
6824
  });
@@ -6556,6 +6832,63 @@ function registerShutdown(deps2) {
6556
6832
  onShutdown: deps2.onShutdown
6557
6833
  });
6558
6834
  }
6835
+
6836
+ // src/server/pre-context-services.ts
6837
+ import * as path15 from "node:path";
6838
+ import { createRequire as createRequire2 } from "node:module";
6839
+ import { WebSocket as WebSocket2 } from "ws";
6840
+ import { DefaultTokenCounter } from "@wrongstack/core/infrastructure";
6841
+ import {
6842
+ AgentStatusTracker,
6843
+ AnnotationsStore,
6844
+ DEFAULT_SESSION_PRUNE_DAYS,
6845
+ DefaultModelsRegistry,
6846
+ DefaultModeStore,
6847
+ DefaultPromptLoader,
6848
+ DefaultSessionReader,
6849
+ DefaultSessionStore,
6850
+ DefaultSkillLoader,
6851
+ DefaultSystemPromptBuilder,
6852
+ EventBus,
6853
+ FleetNotifier,
6854
+ GlobalMailbox,
6855
+ PromptUsageStore,
6856
+ ProviderRegistry,
6857
+ SkillInstaller,
6858
+ TOKENS,
6859
+ ToolRegistry,
6860
+ Context,
6861
+ applyToolDescriptionModes,
6862
+ applyToolResultRenderModes,
6863
+ configureChildEnvGitIdentity,
6864
+ resolveContextWindowPolicy,
6865
+ getSessionRegistry,
6866
+ makeMailboxTool,
6867
+ makeMailInboxTool,
6868
+ makeFleetStatusTool,
6869
+ makeMailSendTool
6870
+ } from "@wrongstack/core";
6871
+ import {
6872
+ createSuperMemoryTools
6873
+ } from "@wrongstack/super-memory";
6874
+ import { MCPRegistry } from "@wrongstack/mcp";
6875
+ import { buildProviderFactoriesFromRegistry } from "@wrongstack/providers";
6876
+ import { createDefaultContainer } from "@wrongstack/runtime";
6877
+ import {
6878
+ builtinToolsPack,
6879
+ configureDangerBypass,
6880
+ configureExecPolicy,
6881
+ forgetTool,
6882
+ relatedMemoryTool,
6883
+ rememberTool,
6884
+ searchMemoryTool
6885
+ } from "@wrongstack/tools";
6886
+ import { toErrorMessage as toErrorMessage5 } from "@wrongstack/core/utils";
6887
+
6888
+ // src/server/setup-screen.ts
6889
+ import { expectDefined as expectDefined2 } from "@wrongstack/core";
6890
+ import { toErrorMessage as toErrorMessage4 } from "@wrongstack/core/utils";
6891
+ import { makeProviderFromConfig } from "@wrongstack/providers";
6559
6892
  var UNCONFIGURED_CAPABILITIES = {
6560
6893
  tools: false,
6561
6894
  parallelTools: false,
@@ -6595,7 +6928,7 @@ function logCreateFailure(event, err) {
6595
6928
  JSON.stringify({
6596
6929
  level: "error",
6597
6930
  event,
6598
- message: toErrorMessage(err),
6931
+ message: toErrorMessage4(err),
6599
6932
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
6600
6933
  })
6601
6934
  );
@@ -6620,7 +6953,7 @@ function resolveSetupProvider(opts) {
6620
6953
  const savedProviders = config.providers ?? {};
6621
6954
  const firstKey = Object.keys(savedProviders)[0];
6622
6955
  if (firstKey) {
6623
- const firstProvider = expectDefined(savedProviders[firstKey]);
6956
+ const firstProvider = expectDefined2(savedProviders[firstKey]);
6624
6957
  try {
6625
6958
  const provider2 = makeProviderFromConfig(firstKey, {
6626
6959
  ...firstProvider,
@@ -6700,6 +7033,11 @@ function seedContextMeta(config, context) {
6700
7033
  const tgMs = tgExt?.["longToolThresholdMs"];
6701
7034
  meta["tgLongToolMs"] = typeof tgMs === "number" ? tgMs : 3e4;
6702
7035
  }
7036
+
7037
+ // src/server/model-auto-discovery.ts
7038
+ import * as fs11 from "node:fs/promises";
7039
+ import * as path14 from "node:path";
7040
+ import { COMPATIBLE_PRESETS, discoverOpenAICompatibleModels } from "@wrongstack/providers";
6703
7041
  function isOverlayRegistry(value) {
6704
7042
  return !!value && typeof value === "object" && typeof value.mergeOverlay === "function";
6705
7043
  }
@@ -6724,7 +7062,7 @@ function eligibleProviders(config) {
6724
7062
  }
6725
7063
  async function readCache(file) {
6726
7064
  try {
6727
- return JSON.parse(await fs4.readFile(file, "utf8"));
7065
+ return JSON.parse(await fs11.readFile(file, "utf8"));
6728
7066
  } catch {
6729
7067
  return {};
6730
7068
  }
@@ -6734,7 +7072,7 @@ async function discoverAndMergeWebuiProviders(opts) {
6734
7072
  if (!isOverlayRegistry(registry)) return;
6735
7073
  const targets = eligibleProviders(opts.config);
6736
7074
  if (targets.length === 0) return;
6737
- const cacheFile = path5.join(opts.cacheDir, "discovered-models-cache.json");
7075
+ const cacheFile = path14.join(opts.cacheDir, "discovered-models-cache.json");
6738
7076
  const cache = await readCache(cacheFile);
6739
7077
  let cacheDirty = false;
6740
7078
  await Promise.all(
@@ -6771,8 +7109,8 @@ async function discoverAndMergeWebuiProviders(opts) {
6771
7109
  );
6772
7110
  if (cacheDirty) {
6773
7111
  try {
6774
- await fs4.mkdir(path5.dirname(cacheFile), { recursive: true });
6775
- await fs4.writeFile(cacheFile, JSON.stringify(cache), "utf8");
7112
+ await fs11.mkdir(path14.dirname(cacheFile), { recursive: true });
7113
+ await fs11.writeFile(cacheFile, JSON.stringify(cache), "utf8");
6776
7114
  } catch {
6777
7115
  opts.logger?.debug?.("provider auto-discovery cache write failed");
6778
7116
  }
@@ -6794,20 +7132,22 @@ async function createPreContextServices(input) {
6794
7132
  await modelsRegistry.refresh();
6795
7133
  logger.info("models.dev catalog refreshed");
6796
7134
  } catch (err) {
6797
- logger.warn(`models.dev refresh failed (${toErrorMessage(err)}); using cached catalog`);
7135
+ logger.warn(`models.dev refresh failed (${toErrorMessage5(err)}); using cached catalog`);
6798
7136
  }
6799
7137
  }
6800
7138
  try {
6801
7139
  await discoverAndMergeWebuiProviders({
6802
7140
  config,
6803
7141
  registry: modelsRegistry,
6804
- cacheDir: path5.dirname(wpaths.modelsCache),
7142
+ cacheDir: path15.dirname(wpaths.modelsCache),
6805
7143
  logger
6806
7144
  });
6807
7145
  } catch (err) {
6808
- logger.debug(`provider auto-discovery skipped: ${toErrorMessage(err)}`);
7146
+ logger.debug(`provider auto-discovery skipped: ${toErrorMessage5(err)}`);
6809
7147
  }
6810
- const container = createDefaultContainer({ config, wpaths, logger, modelsRegistry });
7148
+ const events = opts.services?.events ?? new EventBus();
7149
+ events.setLogger(logger);
7150
+ const container = createDefaultContainer({ config, wpaths, logger, modelsRegistry, events });
6811
7151
  const configStore = opts.services?.configStore ?? container.resolve(TOKENS.ConfigStore);
6812
7152
  const providerRegistry = new ProviderRegistry();
6813
7153
  try {
@@ -6815,22 +7155,23 @@ async function createPreContextServices(input) {
6815
7155
  for (const f of factories) providerRegistry.register(f);
6816
7156
  console.log("[WebUI] Provider registry loaded:", providerRegistry.list().length, "providers");
6817
7157
  } catch (err) {
6818
- console.warn(JSON.stringify({ level: "warn", event: "webui.provider_registry_load_failed", message: toErrorMessage(err), timestamp: (/* @__PURE__ */ new Date()).toISOString() }));
7158
+ console.warn(JSON.stringify({ level: "warn", event: "webui.provider_registry_load_failed", message: toErrorMessage5(err), timestamp: (/* @__PURE__ */ new Date()).toISOString() }));
6819
7159
  }
6820
7160
  const toolRegistry = opts.services?.toolRegistry ?? (() => {
6821
7161
  const r = new ToolRegistry();
6822
7162
  r.registerAllOrThrow([...builtinToolsPack.tools ?? []], builtinToolsPack.name);
6823
7163
  return r;
6824
7164
  })();
6825
- const memoryStore = new DefaultMemoryStore({ paths: wpaths });
7165
+ const memoryStore = container.resolve(TOKENS.MemoryStore);
6826
7166
  if (config.features.memory) {
6827
7167
  toolRegistry.register(rememberTool(memoryStore));
6828
7168
  toolRegistry.register(forgetTool(memoryStore));
6829
7169
  toolRegistry.register(searchMemoryTool(memoryStore));
6830
7170
  toolRegistry.register(relatedMemoryTool(memoryStore));
7171
+ if (isSuperMemoryService(memoryStore)) {
7172
+ for (const tool of createSuperMemoryTools(memoryStore)) toolRegistry.register(tool);
7173
+ }
6831
7174
  }
6832
- const events = opts.services?.events ?? new EventBus();
6833
- events.setLogger(logger);
6834
7175
  toolRegistry.register(makeMailboxTool({ projectDir: wpaths.projectDir, events }));
6835
7176
  toolRegistry.register(makeMailSendTool({ projectDir: wpaths.projectDir, events }));
6836
7177
  toolRegistry.register(makeMailInboxTool({ projectDir: wpaths.projectDir, events }));
@@ -6839,6 +7180,7 @@ async function createPreContextServices(input) {
6839
7180
  applyToolResultRenderModes(toolRegistry, config.tools?.resultRenderMode);
6840
7181
  configureExecPolicy(config.tools?.exec ?? {});
6841
7182
  configureDangerBypass(config.tools?.exec?.danger ?? {});
7183
+ configureChildEnvGitIdentity(config.git?.identity ?? null);
6842
7184
  console.log("[WebUI] Tool registry loaded:", toolRegistry.list().length, "tools");
6843
7185
  const mcpRegistry = new MCPRegistry({ toolRegistry, events, log: logger, cacheDir: wpaths.cacheDir });
6844
7186
  if (config.features.mcp && config.mcpServers) {
@@ -6890,7 +7232,7 @@ async function createPreContextServices(input) {
6890
7232
  sessionId: session.id,
6891
7233
  projectSlug: wpaths.projectSlug,
6892
7234
  projectRoot,
6893
- projectName: path5.basename(projectRoot),
7235
+ projectName: path15.basename(projectRoot),
6894
7236
  workingDir,
6895
7237
  clientType: "webui",
6896
7238
  pid: process.pid,
@@ -6916,13 +7258,13 @@ async function createPreContextServices(input) {
6916
7258
  startWorktreeTelemetryBridge,
6917
7259
  startToolTelemetryBridge,
6918
7260
  startCostTelemetryBridge
6919
- } = await import('@wrongstack/core');
7261
+ } = await import("@wrongstack/core");
6920
7262
  const hqTelemetry = createHqPublisherFromEnv({
6921
7263
  clientKind: "webui",
6922
7264
  projectRoot,
6923
- projectName: path5.basename(projectRoot),
7265
+ projectName: path15.basename(projectRoot),
6924
7266
  appConfig: config,
6925
- socketFactory: (url) => new WebSocket(url)
7267
+ socketFactory: (url) => new WebSocket2(url)
6926
7268
  });
6927
7269
  if (hqTelemetry) {
6928
7270
  hqTelemetry.connect();
@@ -6932,7 +7274,7 @@ async function createPreContextServices(input) {
6932
7274
  events,
6933
7275
  sessionId: session.id,
6934
7276
  projectRoot,
6935
- projectName: path5.basename(projectRoot),
7277
+ projectName: path15.basename(projectRoot),
6936
7278
  globalRoot: wpaths.globalRoot,
6937
7279
  initialAgents: statusTracker?.getAgents(),
6938
7280
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -7021,7 +7363,7 @@ async function createPreContextServices(input) {
7021
7363
  const modelCapabilitiesRef = { current: modelCapabilities };
7022
7364
  const skillLoader = config.features.skills ? new DefaultSkillLoader({ paths: wpaths }) : void 0;
7023
7365
  const skillInstaller = config.features.skills ? new SkillInstaller({
7024
- manifestPath: path5.join(wpaths.globalRoot, "installed-skills.json"),
7366
+ manifestPath: path15.join(wpaths.globalRoot, "installed-skills.json"),
7025
7367
  projectSkillsDir: wpaths.inProjectSkills,
7026
7368
  globalSkillsDir: wpaths.globalSkills,
7027
7369
  projectHash: wpaths.projectHash,
@@ -7030,8 +7372,8 @@ async function createPreContextServices(input) {
7030
7372
  const promptsEnabled = config.features.prompts !== false;
7031
7373
  const bundledPromptsDir = promptsEnabled ? (() => {
7032
7374
  try {
7033
- const req = createRequire(import.meta.url);
7034
- return path5.join(path5.dirname(req.resolve("@wrongstack/core/package.json")), "data", "prompts");
7375
+ const req = createRequire2(import.meta.url);
7376
+ return path15.join(path15.dirname(req.resolve("@wrongstack/core/package.json")), "data", "prompts");
7035
7377
  } catch {
7036
7378
  return void 0;
7037
7379
  }
@@ -7112,8 +7454,33 @@ async function createPreContextServices(input) {
7112
7454
  needsSetup
7113
7455
  };
7114
7456
  }
7457
+ function isSuperMemoryService(memoryStore) {
7458
+ const value = memoryStore;
7459
+ return typeof value["retrieveForPath"] === "function" && typeof value["searchSuper"] === "function" && typeof value["graphFor"] === "function" && typeof value["verify"] === "function" && typeof value["hygiene"] === "function" && typeof value["listCandidates"] === "function";
7460
+ }
7461
+
7462
+ // src/server/start-webui.ts
7463
+ import * as path22 from "node:path";
7464
+ import {
7465
+ createDefaultPipelines,
7466
+ createSessionEventBridge,
7467
+ DEFAULT_CONTEXT_WINDOW_MODE_ID as DEFAULT_CONTEXT_WINDOW_MODE_ID2,
7468
+ expectDefined as expectDefined3,
7469
+ resolveSessionLoggingConfig,
7470
+ watchProviderConfig
7471
+ } from "@wrongstack/core";
7472
+ import { toErrorMessage as toErrorMessage10 } from "@wrongstack/core/utils";
7473
+ import { makeProviderFromConfig as makeProviderFromConfig3 } from "@wrongstack/providers";
7474
+ import {
7475
+ ensureSessionShell
7476
+ } from "@wrongstack/tools";
7477
+
7478
+ // src/server/boot.ts
7479
+ import {
7480
+ bootConfig as coreBootConfig
7481
+ } from "@wrongstack/core";
7115
7482
  async function bootConfig() {
7116
- const { config, vault, globalConfigPath, projectRoot, wpaths, logger } = await bootConfig$1({
7483
+ const { config, vault, globalConfigPath, projectRoot, wpaths, logger } = await coreBootConfig({
7117
7484
  appLabel: "WebUI"
7118
7485
  });
7119
7486
  return { config, vault, globalConfigPath, projectRoot, wpaths, logger };
@@ -7121,6 +7488,35 @@ async function bootConfig() {
7121
7488
  function patchConfig(config, updates) {
7122
7489
  return Object.freeze({ ...config, ...updates });
7123
7490
  }
7491
+
7492
+ // src/server/backend-services.ts
7493
+ import {
7494
+ Agent,
7495
+ AutoCompactionMiddleware as AutoCompactionMiddlewareCtor,
7496
+ BrainMonitor,
7497
+ CollaborationBus as CollaborationBusCtor,
7498
+ DEFAULT_TOOLS_CONFIG,
7499
+ createStrategyCompactor,
7500
+ collabInjectMiddleware,
7501
+ collabPauseMiddleware,
7502
+ estimateRequestTokensCalibrated,
7503
+ installDesignStudioMiddleware,
7504
+ ObservableBrainArbiter as ObservableBrainArbiterCtor,
7505
+ resolveContextWindowPolicy as resolveContextWindowPolicy2,
7506
+ createAutonomyBrain,
7507
+ createTieredBrainArbiter,
7508
+ DefaultBrainArbiter,
7509
+ GlobalMailbox as GlobalMailbox2,
7510
+ mailboxSessionTag,
7511
+ SessionMemoryConsolidator,
7512
+ TOKENS as TOKENS2,
7513
+ ToolExecutor
7514
+ } from "@wrongstack/core";
7515
+
7516
+ // src/server/collaboration-ws-handler.ts
7517
+ import { randomUUID } from "node:crypto";
7518
+ import { toErrorMessage as toErrorMessage6 } from "@wrongstack/core/utils";
7519
+ var REPLAY_LIMIT = 50;
7124
7520
  var PAUSE_TIMEOUT_MS = 6e4;
7125
7521
  var CollaborationWebSocketHandler = class {
7126
7522
  constructor(events, logger, reader, annotations, bus) {
@@ -7248,7 +7644,7 @@ var CollaborationWebSocketHandler = class {
7248
7644
  if (this.reader) {
7249
7645
  this.replayHistory(ws, sessionId).catch((err) => {
7250
7646
  this.logger.debug?.(
7251
- `collab: replay failed for ${sessionId}: ${toErrorMessage(err)}`
7647
+ `collab: replay failed for ${sessionId}: ${toErrorMessage6(err)}`
7252
7648
  );
7253
7649
  });
7254
7650
  }
@@ -7366,7 +7762,7 @@ var CollaborationWebSocketHandler = class {
7366
7762
  this.send(
7367
7763
  ws,
7368
7764
  this.errorMessage(
7369
- `annotation rejected: ${toErrorMessage(err)}`
7765
+ `annotation rejected: ${toErrorMessage6(err)}`
7370
7766
  )
7371
7767
  );
7372
7768
  }
@@ -7433,7 +7829,7 @@ var CollaborationWebSocketHandler = class {
7433
7829
  this.send(
7434
7830
  ws,
7435
7831
  this.errorMessage(
7436
- `resolve failed: ${toErrorMessage(err)}`
7832
+ `resolve failed: ${toErrorMessage6(err)}`
7437
7833
  )
7438
7834
  );
7439
7835
  }
@@ -7481,7 +7877,7 @@ var CollaborationWebSocketHandler = class {
7481
7877
  if (p.ws.readyState === 1) p.ws.send(data);
7482
7878
  } catch (err) {
7483
7879
  this.logger.debug?.(
7484
- `collab broadcast failed: ${toErrorMessage(err)}`
7880
+ `collab broadcast failed: ${toErrorMessage6(err)}`
7485
7881
  );
7486
7882
  }
7487
7883
  }
@@ -7508,11 +7904,11 @@ var CollaborationWebSocketHandler = class {
7508
7904
  }
7509
7905
  } catch (err) {
7510
7906
  this.logger.debug?.(
7511
- `collab: session reader rejected ${sessionId}: ${toErrorMessage(err)}`
7907
+ `collab: session reader rejected ${sessionId}: ${toErrorMessage6(err)}`
7512
7908
  );
7513
7909
  return;
7514
7910
  }
7515
- const tail2 = all.slice(-50);
7911
+ const tail2 = all.slice(-REPLAY_LIMIT);
7516
7912
  if (tail2.length === 0) return;
7517
7913
  for (const raw of tail2) {
7518
7914
  const ev = raw;
@@ -7589,7 +7985,7 @@ var CollaborationWebSocketHandler = class {
7589
7985
  if (p.ws.readyState === 1) p.ws.send(data);
7590
7986
  } catch (err) {
7591
7987
  this.logger.debug?.(
7592
- `collab broadcast failed: ${toErrorMessage(err)}`
7988
+ `collab broadcast failed: ${toErrorMessage6(err)}`
7593
7989
  );
7594
7990
  }
7595
7991
  }
@@ -7841,6 +8237,17 @@ var CollaborationWebSocketHandler = class {
7841
8237
  }
7842
8238
  }
7843
8239
  };
8240
+
8241
+ // src/server/codebase-indexing.ts
8242
+ import * as fs12 from "node:fs";
8243
+ import * as path16 from "node:path";
8244
+ import {
8245
+ cancelPendingReindexes,
8246
+ enqueueReindex,
8247
+ isIndexableFile,
8248
+ runStartupIndex,
8249
+ shutdownCodebaseIndexHost
8250
+ } from "@wrongstack/tools";
7844
8251
  var IGNORE_DIRS = /* @__PURE__ */ new Set([
7845
8252
  "node_modules",
7846
8253
  ".git",
@@ -7886,7 +8293,7 @@ function setupWebUICodebaseIndexing(deps2) {
7886
8293
  if (!filename) return;
7887
8294
  const rel = filename.toString();
7888
8295
  if (isIgnored(rel)) return;
7889
- const abs = path5.resolve(deps2.projectRoot, rel);
8296
+ const abs = path16.resolve(deps2.projectRoot, rel);
7890
8297
  enqueueFile(abs);
7891
8298
  });
7892
8299
  watcher.on("error", (err) => deps2.logger.debug(`webui codebase index watcher error: ${err}`));
@@ -7899,7 +8306,7 @@ function setupWebUICodebaseIndexing(deps2) {
7899
8306
  }
7900
8307
  function enqueueFile(filePath) {
7901
8308
  if (!idx.onEdit && !idx.watchExternal) return;
7902
- const abs = path5.isAbsolute(filePath) ? path5.normalize(filePath) : path5.resolve(deps2.projectRoot, filePath);
8309
+ const abs = path16.isAbsolute(filePath) ? path16.normalize(filePath) : path16.resolve(deps2.projectRoot, filePath);
7903
8310
  if (!isInside2(deps2.projectRoot, abs) || !isIndexableFile(abs)) return;
7904
8311
  enqueueReindex({
7905
8312
  projectRoot: deps2.projectRoot,
@@ -7936,15 +8343,23 @@ function isIgnored(rel) {
7936
8343
  return rel.split(/[/\\]/).some((seg) => IGNORE_DIRS.has(seg));
7937
8344
  }
7938
8345
  function isInside2(root, target) {
7939
- const normalizedRoot = path5.resolve(root);
7940
- const normalizedTarget = path5.resolve(target);
7941
- return normalizedTarget === normalizedRoot || normalizedTarget.startsWith(normalizedRoot + path5.sep);
8346
+ const normalizedRoot = path16.resolve(root);
8347
+ const normalizedTarget = path16.resolve(target);
8348
+ return normalizedTarget === normalizedRoot || normalizedTarget.startsWith(normalizedRoot + path16.sep);
7942
8349
  }
8350
+
8351
+ // src/server/discover-mailbox-bridge.ts
8352
+ import { spawn as spawn3 } from "node:child_process";
8353
+ import { createRequire as createRequire3 } from "node:module";
8354
+ import { existsSync } from "node:fs";
8355
+ import { dirname as dirname8, join as join12 } from "node:path";
8356
+ import { resolveProjectDir, wstackGlobalRoot as wstackGlobalRoot2 } from "@wrongstack/core";
8357
+ import { readLiveLock } from "@wrongstack/core/coordination";
7943
8358
  var MAILBOX_BRIDGE_BOOT_TIMEOUT_MS = 5e3;
7944
8359
  async function discoverMailboxBridgeForWebui(params) {
7945
8360
  const mode = params.config?.features?.mailboxBridge ?? "auto";
7946
8361
  if (mode === "off") return;
7947
- const projectDir = resolveProjectDir(params.projectRoot, wstackGlobalRoot$1());
8362
+ const projectDir = resolveProjectDir(params.projectRoot, wstackGlobalRoot2());
7948
8363
  let result = await readLiveLock(projectDir);
7949
8364
  let spawnedPid = null;
7950
8365
  if (result.kind !== "live") {
@@ -8010,7 +8425,7 @@ async function waitForLiveMailboxBridge(projectDir, timeoutMs) {
8010
8425
  function spawnMailboxBridge(projectRoot, logger) {
8011
8426
  const invocation = mailboxServeInvocation(projectRoot);
8012
8427
  try {
8013
- const child = spawn(invocation.command, invocation.args, {
8428
+ const child = spawn3(invocation.command, invocation.args, {
8014
8429
  cwd: projectRoot,
8015
8430
  detached: process.platform !== "win32" && !invocation.useShell,
8016
8431
  env: process.env,
@@ -8041,7 +8456,7 @@ function mailboxServeInvocation(projectRoot) {
8041
8456
  return { command: process.execPath, args: [explicitCliEntry, "mailbox", "serve"] };
8042
8457
  }
8043
8458
  try {
8044
- const require2 = createRequire(import.meta.url);
8459
+ const require2 = createRequire3(import.meta.url);
8045
8460
  const cliEntry = require2.resolve("@wrongstack/cli");
8046
8461
  return { command: process.execPath, args: [cliEntry, "mailbox", "serve"] };
8047
8462
  } catch {
@@ -8065,9 +8480,9 @@ function mailboxServeInvocation(projectRoot) {
8065
8480
  function findWorkspaceCliEntry(projectRoot) {
8066
8481
  let dir = projectRoot;
8067
8482
  for (let i = 0; i < 6; i++) {
8068
- const candidate = join(dir, "packages", "cli", "dist", "index.js");
8483
+ const candidate = join12(dir, "packages", "cli", "dist", "index.js");
8069
8484
  if (existsSync(candidate)) return candidate;
8070
- const parent = dirname(dir);
8485
+ const parent = dirname8(dir);
8071
8486
  if (parent === dir) return null;
8072
8487
  dir = parent;
8073
8488
  }
@@ -8076,10 +8491,15 @@ function findWorkspaceCliEntry(projectRoot) {
8076
8491
  function sleep(ms) {
8077
8492
  return new Promise((resolve10) => setTimeout(resolve10, ms));
8078
8493
  }
8494
+
8495
+ // src/server/terminal-ws-handler.ts
8496
+ import { spawn as spawnChild } from "node:child_process";
8497
+ import { createRequire as createRequire4 } from "node:module";
8498
+ import { toErrorMessage as toErrorMessage7 } from "@wrongstack/core/utils";
8079
8499
  var MAX_SESSIONS_PER_CLIENT = 8;
8080
8500
  var DEFAULT_COLS = 80;
8081
8501
  var DEFAULT_ROWS = 24;
8082
- var requireFromHere = createRequire(import.meta.url);
8502
+ var requireFromHere = createRequire4(import.meta.url);
8083
8503
  var cachedNodePty;
8084
8504
  var TerminalWebSocketHandler = class {
8085
8505
  constructor(getCwd, logger, loadNodePty = defaultLoadNodePty, killProcessTree = defaultKillProcessTree) {
@@ -8157,8 +8577,8 @@ var TerminalWebSocketHandler = class {
8157
8577
  ...windowsPtyOptions()
8158
8578
  });
8159
8579
  } catch (err) {
8160
- const msg = `Integrated terminal failed to start: ${toErrorMessage(err)}`;
8161
- this.logger.warn?.(`terminal spawn failed: ${toErrorMessage(err)}`);
8580
+ const msg = `Integrated terminal failed to start: ${toErrorMessage7(err)}`;
8581
+ this.logger.warn?.(`terminal spawn failed: ${toErrorMessage7(err)}`);
8162
8582
  this.send(ws, { type: "terminal.output", payload: { id: payload.id, data: `${msg}\r
8163
8583
  ` } });
8164
8584
  this.send(ws, { type: "terminal.exit", payload: { id: payload.id, exitCode: -1 } });
@@ -8211,7 +8631,7 @@ var TerminalWebSocketHandler = class {
8211
8631
  try {
8212
8632
  pty.kill();
8213
8633
  } catch (err) {
8214
- this.logger.warn?.(`${reason} failed: ${toErrorMessage(err)}`);
8634
+ this.logger.warn?.(`${reason} failed: ${toErrorMessage7(err)}`);
8215
8635
  }
8216
8636
  }
8217
8637
  killWindowsProcessTree(pty, reason) {
@@ -8223,7 +8643,7 @@ var TerminalWebSocketHandler = class {
8223
8643
  } catch {
8224
8644
  }
8225
8645
  } catch (err) {
8226
- this.logger.warn?.(`${reason} taskkill failed: ${toErrorMessage(err)}`);
8646
+ this.logger.warn?.(`${reason} taskkill failed: ${toErrorMessage7(err)}`);
8227
8647
  }
8228
8648
  }
8229
8649
  send(ws, msg) {
@@ -8254,7 +8674,7 @@ function windowsPtyOptions() {
8254
8674
  return { useConptyDll: true };
8255
8675
  }
8256
8676
  function defaultKillProcessTree(pid) {
8257
- const child = spawn("taskkill", ["/PID", String(pid), "/T", "/F"], {
8677
+ const child = spawnChild("taskkill", ["/PID", String(pid), "/T", "/F"], {
8258
8678
  stdio: "ignore",
8259
8679
  windowsHide: true
8260
8680
  });
@@ -8267,6 +8687,14 @@ function clampDim(value, fallback) {
8267
8687
  if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
8268
8688
  return Math.max(1, Math.min(1e3, Math.floor(value)));
8269
8689
  }
8690
+
8691
+ // src/server/backend-services.ts
8692
+ import { makeLightSubagentFactory } from "@wrongstack/runtime";
8693
+ import {
8694
+ createSuperMemoryToolCallMiddleware,
8695
+ createSuperMemoryTurnMiddleware
8696
+ } from "@wrongstack/super-memory";
8697
+ import { toErrorMessage as toErrorMessage8 } from "@wrongstack/core/utils";
8270
8698
  async function createAgentServices(input) {
8271
8699
  const {
8272
8700
  config,
@@ -8281,15 +8709,37 @@ async function createAgentServices(input) {
8281
8709
  providerRegistry,
8282
8710
  modelsRegistry,
8283
8711
  events,
8712
+ memoryStore,
8284
8713
  modelCapabilitiesRef
8285
8714
  } = input;
8286
- const collabBus = new CollaborationBus();
8715
+ const collabBus = new CollaborationBusCtor();
8287
8716
  const pipelines = input.pipelines;
8288
8717
  const collabInject = collabInjectMiddleware(collabBus, { logger });
8289
8718
  pipelines.toolCall.prepend(collabInject);
8290
8719
  const collabPause = collabPauseMiddleware(collabBus, { logger });
8291
8720
  pipelines.toolCall.prepend(collabPause);
8292
8721
  installDesignStudioMiddleware({ pipelines, ctx: context });
8722
+ if (config.features.memory !== false && config.superMemory?.enabled !== false && isSuperMemoryRetriever(memoryStore)) {
8723
+ if (config.superMemory?.inject?.toolResults !== false) {
8724
+ pipelines.toolCall.use(createSuperMemoryToolCallMiddleware({
8725
+ memory: memoryStore,
8726
+ maxHintsPerTool: config.superMemory?.inject?.maxHintsPerTool,
8727
+ maxCharsPerTool: config.superMemory?.inject?.maxCharsPerTool,
8728
+ minScore: config.superMemory?.inject?.minScore,
8729
+ repeatCooldownMs: config.superMemory?.inject?.repeatCooldownMs,
8730
+ verifyOnMutation: config.superMemory?.hygiene?.autoOnFileChange,
8731
+ triggers: config.superMemory?.inject?.triggers
8732
+ }));
8733
+ }
8734
+ if (config.superMemory?.inject?.turnContext !== false) {
8735
+ pipelines.request.use(createSuperMemoryTurnMiddleware({
8736
+ memory: memoryStore,
8737
+ maxMemories: config.superMemory?.inject?.maxTurnMemories,
8738
+ maxChars: config.superMemory?.inject?.maxCharsPerTurn,
8739
+ minScore: config.superMemory?.inject?.minScore
8740
+ }));
8741
+ }
8742
+ }
8293
8743
  const codebaseIndexing = setupWebUICodebaseIndexing({
8294
8744
  config,
8295
8745
  context,
@@ -8303,7 +8753,7 @@ async function createAgentServices(input) {
8303
8753
  summarizerModel: config.context?.summarizerModel,
8304
8754
  llmSelector: config.context?.llmSelector
8305
8755
  });
8306
- const initialContextPolicy = resolveContextWindowPolicy(config.context);
8756
+ const initialContextPolicy = resolveContextWindowPolicy2(config.context);
8307
8757
  let autoCompactor;
8308
8758
  if (config.context?.autoCompact !== false) {
8309
8759
  let effectiveMaxContext = config.context?.effectiveMaxContext ?? 0;
@@ -8320,7 +8770,7 @@ async function createAgentServices(input) {
8320
8770
  }
8321
8771
  }
8322
8772
  if (!effectiveMaxContext) effectiveMaxContext = provider.capabilities.maxContext;
8323
- autoCompactor = new AutoCompactionMiddleware(
8773
+ autoCompactor = new AutoCompactionMiddlewareCtor(
8324
8774
  compactor,
8325
8775
  effectiveMaxContext,
8326
8776
  (ctx) => estimateRequestTokensCalibrated(
@@ -8348,7 +8798,7 @@ async function createAgentServices(input) {
8348
8798
  const updateAutoCompactionMaxContext = async (newProvider, providerId = newProvider.id, providerCfg) => {
8349
8799
  await modelsRegistry.refresh().catch((err) => {
8350
8800
  logger.warn(
8351
- `models.dev refresh failed for ${providerId}/${context.model}: ${toErrorMessage(err)}; using cached catalog`
8801
+ `models.dev refresh failed for ${providerId}/${context.model}: ${toErrorMessage8(err)}; using cached catalog`
8352
8802
  );
8353
8803
  });
8354
8804
  const currentConfig = input.config;
@@ -8385,9 +8835,9 @@ async function createAgentServices(input) {
8385
8835
  maxContext: newMaxContext
8386
8836
  });
8387
8837
  };
8388
- const secretScrubber = container.resolve(TOKENS.SecretScrubber);
8389
- const renderer = container.has(TOKENS.Renderer) ? container.resolve(TOKENS.Renderer) : void 0;
8390
- const permissionPolicy = container.resolve(TOKENS.PermissionPolicy);
8838
+ const secretScrubber = container.resolve(TOKENS2.SecretScrubber);
8839
+ const renderer = container.has(TOKENS2.Renderer) ? container.resolve(TOKENS2.Renderer) : void 0;
8840
+ const permissionPolicy = container.resolve(TOKENS2.PermissionPolicy);
8391
8841
  const toolExecutor = new ToolExecutor(toolRegistry, {
8392
8842
  permissionPolicy,
8393
8843
  secretScrubber,
@@ -8398,7 +8848,7 @@ async function createAgentServices(input) {
8398
8848
  perIterationOutputCapBytes: config.tools?.perIterationOutputCapBytes ?? DEFAULT_TOOLS_CONFIG.perIterationOutputCapBytes,
8399
8849
  tracer: void 0
8400
8850
  });
8401
- const webuiLogger = container.resolve(TOKENS.Logger);
8851
+ const webuiLogger = container.resolve(TOKENS2.Logger);
8402
8852
  void discoverMailboxBridgeForWebui({
8403
8853
  projectRoot,
8404
8854
  config,
@@ -8424,6 +8874,9 @@ async function createAgentServices(input) {
8424
8874
  confirmAwaiter: void 0,
8425
8875
  toolExecutor
8426
8876
  });
8877
+ if (config.features.memory && config.features.memoryConsolidation !== false) {
8878
+ agent.extensions.register(new SessionMemoryConsolidator({ memoryStore }));
8879
+ }
8427
8880
  console.log("[WebUI] Agent initialized");
8428
8881
  const brainSettings = { maxAutoRisk: "medium" };
8429
8882
  const autonomousBrain = {
@@ -8434,7 +8887,7 @@ async function createAgentServices(input) {
8434
8887
  // the tiered ceiling gates risk — keep inner permissive
8435
8888
  }).decide(request)
8436
8889
  };
8437
- const brain = new ObservableBrainArbiter(
8890
+ const brain = new ObservableBrainArbiterCtor(
8438
8891
  createTieredBrainArbiter({
8439
8892
  policy: new DefaultBrainArbiter(),
8440
8893
  autonomous: autonomousBrain,
@@ -8442,7 +8895,7 @@ async function createAgentServices(input) {
8442
8895
  }),
8443
8896
  events
8444
8897
  );
8445
- container.bind(TOKENS.BrainArbiter, () => brain);
8898
+ container.bind(TOKENS2.BrainArbiter, () => brain);
8446
8899
  const brainLog = [];
8447
8900
  const pushBrainLog = (entry) => {
8448
8901
  brainLog.push(entry);
@@ -8475,7 +8928,7 @@ async function createAgentServices(input) {
8475
8928
  outcome: e.decision.type === "deny" ? e.decision.reason : ""
8476
8929
  })
8477
8930
  );
8478
- const brainMailbox = new GlobalMailbox(wpaths.projectDir, events);
8931
+ const brainMailbox = new GlobalMailbox2(wpaths.projectDir, events);
8479
8932
  const brainMonitor = new BrainMonitor({
8480
8933
  events,
8481
8934
  brain,
@@ -8568,14 +9021,14 @@ async function createAgentServices(input) {
8568
9021
  updateAutoCompactionMaxContext
8569
9022
  };
8570
9023
  }
9024
+ function isSuperMemoryRetriever(memoryStore) {
9025
+ const value = memoryStore;
9026
+ return typeof value["retrieveForPath"] === "function" && typeof value["searchSuper"] === "function";
9027
+ }
8571
9028
 
8572
9029
  // src/server/pending-confirms.ts
8573
- function isDestructivePendingConfirm(confirm) {
8574
- return confirm.riskTier === "destructive" || confirm.decisionSource === "yolo_destructive";
8575
- }
8576
9030
  function resolveYoloEligiblePendingConfirms(pendingConfirms) {
8577
9031
  for (const [id, confirm] of pendingConfirms) {
8578
- if (isDestructivePendingConfirm(confirm)) continue;
8579
9032
  pendingConfirms.delete(id);
8580
9033
  confirm.resolve("yes");
8581
9034
  }
@@ -8731,6 +9184,9 @@ function createConnectionHandler(opts) {
8731
9184
  };
8732
9185
  }
8733
9186
 
9187
+ // src/server/message-dispatcher.ts
9188
+ import path17 from "node:path";
9189
+
8734
9190
  // src/server/autophase-routes.ts
8735
9191
  async function handleAutoPhaseRoute(_ws, msg, handlers) {
8736
9192
  if (!msg.type.startsWith("autophase.")) return false;
@@ -8754,10 +9210,13 @@ async function handleBrainRoute(ws, msg, handlers) {
8754
9210
  return false;
8755
9211
  }
8756
9212
  }
9213
+
9214
+ // src/server/goal-handlers.ts
9215
+ import { resolveWstackPaths } from "@wrongstack/core/utils";
8757
9216
  async function handleGoalGet(projectRoot, broadcast2) {
8758
9217
  try {
8759
9218
  const goalPath = resolveWstackPaths({ projectRoot }).projectGoal;
8760
- const { readFile: readFile11 } = await import('fs/promises');
9219
+ const { readFile: readFile11 } = await import("node:fs/promises");
8761
9220
  const raw = await readFile11(goalPath, "utf8");
8762
9221
  const goal = JSON.parse(raw);
8763
9222
  broadcast2({ type: "goal.updated", payload: goal });
@@ -8811,7 +9270,7 @@ async function handleTasksGet(ctx, ws) {
8811
9270
  const taskPath = ctx.context.meta["task.path"];
8812
9271
  if (typeof taskPath === "string" && taskPath) {
8813
9272
  try {
8814
- const { loadTasks } = await import('@wrongstack/core');
9273
+ const { loadTasks } = await import("@wrongstack/core");
8815
9274
  const file = await loadTasks(taskPath);
8816
9275
  ctx.send(ws, { type: "tasks.updated", payload: sessionPayload(ctx, { tasks: file?.tasks ?? [] }) });
8817
9276
  } catch {
@@ -8831,7 +9290,7 @@ async function handleTaskUpdate(ctx, ws, payload) {
8831
9290
  return;
8832
9291
  }
8833
9292
  try {
8834
- const { loadTasks, saveTasks } = await import('@wrongstack/core');
9293
+ const { loadTasks, saveTasks } = await import("@wrongstack/core");
8835
9294
  const file = await loadTasks(taskPath);
8836
9295
  if (!file) {
8837
9296
  sendResult2(ws, ctx, false, "No task file found.");
@@ -8860,7 +9319,7 @@ async function handlePlanGet(ctx, ws) {
8860
9319
  const sessionId = ctx.context.session?.id ?? "";
8861
9320
  if (typeof planPath === "string" && planPath) {
8862
9321
  try {
8863
- const { loadPlan } = await import('@wrongstack/core');
9322
+ const { loadPlan } = await import("@wrongstack/core");
8864
9323
  const plan = await loadPlan(planPath);
8865
9324
  ctx.send(ws, {
8866
9325
  type: "plan.updated",
@@ -8901,7 +9360,7 @@ async function handlePlanTemplateUse(ctx, ws, template) {
8901
9360
  return;
8902
9361
  }
8903
9362
  try {
8904
- const { getPlanTemplate, loadPlan, savePlan, emptyPlan, addPlanItem } = await import('@wrongstack/core');
9363
+ const { getPlanTemplate, loadPlan, savePlan, emptyPlan, addPlanItem } = await import("@wrongstack/core");
8905
9364
  const tpl = getPlanTemplate(template);
8906
9365
  if (!tpl) {
8907
9366
  sendResult2(ws, ctx, false, `Unknown template "${template}".`);
@@ -8926,7 +9385,7 @@ async function handlePlanItemUpdate(ctx, ws, payload) {
8926
9385
  return;
8927
9386
  }
8928
9387
  try {
8929
- const { mutatePlan, setPlanItemStatus } = await import('@wrongstack/core');
9388
+ const { mutatePlan, setPlanItemStatus } = await import("@wrongstack/core");
8930
9389
  let changed = false;
8931
9390
  const plan = await mutatePlan(planPath, sessionId, async (p) => {
8932
9391
  const before = p.updatedAt;
@@ -8993,6 +9452,45 @@ async function handleWorklistMessage(ctx, ws, msg) {
8993
9452
  return;
8994
9453
  }
8995
9454
  }
9455
+
9456
+ // src/server/kanban-routes.ts
9457
+ import {
9458
+ deserializeTaskGraph,
9459
+ serializeTaskGraph
9460
+ } from "@wrongstack/core";
9461
+ import {
9462
+ addColumn,
9463
+ addGoalMetricToTask,
9464
+ addTask,
9465
+ assignTask,
9466
+ claimReadyTask,
9467
+ copyTaskToBoard,
9468
+ createBoard,
9469
+ duplicateBoard,
9470
+ exportBoardToTaskGraph,
9471
+ generateBoardFromDescription,
9472
+ getBoard,
9473
+ getKanbanOrchestrationSnapshot,
9474
+ getKanbanQueueHealth,
9475
+ getTask,
9476
+ getTaskChain,
9477
+ listReadyTasks,
9478
+ listBoards,
9479
+ mergeTasks,
9480
+ moveTask,
9481
+ parseLinesIntoTasks,
9482
+ removeBoard,
9483
+ removeColumn,
9484
+ removeTask,
9485
+ releaseTaskClaim,
9486
+ setTaskChain,
9487
+ splitTask,
9488
+ syncBoardFromTaskGraph,
9489
+ transferTaskToBoard,
9490
+ updateBoard,
9491
+ updateGoalMetricOnTask,
9492
+ updateTask
9493
+ } from "@wrongstack/kanban";
8996
9494
  function ok(ws, type, data) {
8997
9495
  send(ws, { type, payload: { success: true, data: data ?? null } });
8998
9496
  }
@@ -9593,7 +10091,7 @@ async function handlePrefsRoute(ws, msg, handlers) {
9593
10091
  // src/server/process-handlers.ts
9594
10092
  async function handleProcessList(ws) {
9595
10093
  try {
9596
- const { getProcessRegistry } = await import('@wrongstack/tools');
10094
+ const { getProcessRegistry } = await import("@wrongstack/tools");
9597
10095
  const procs = getProcessRegistry().list();
9598
10096
  send(ws, {
9599
10097
  type: "process.list",
@@ -9620,7 +10118,7 @@ async function handleProcessKill(ws, payload) {
9620
10118
  }
9621
10119
  const { pid } = parsed.value;
9622
10120
  try {
9623
- const { getProcessRegistry } = await import('@wrongstack/tools');
10121
+ const { getProcessRegistry } = await import("@wrongstack/tools");
9624
10122
  const proc = getProcessRegistry().get(pid);
9625
10123
  if (proc?.protected) {
9626
10124
  sendResult(ws, false, `Cannot kill protected process (PID ${pid})`);
@@ -9634,7 +10132,7 @@ async function handleProcessKill(ws, payload) {
9634
10132
  }
9635
10133
  async function handleProcessKillAll(ws) {
9636
10134
  try {
9637
- const { getProcessRegistry } = await import('@wrongstack/tools');
10135
+ const { getProcessRegistry } = await import("@wrongstack/tools");
9638
10136
  getProcessRegistry().killAll();
9639
10137
  sendResult(ws, true, "All processes killed");
9640
10138
  } catch (err) {
@@ -9944,7 +10442,7 @@ function createMessageDispatcher(opts) {
9944
10442
  skillLoader: deps2.skillLoader,
9945
10443
  skillInstaller: deps2.skillInstaller,
9946
10444
  projectRoot,
9947
- projectSkillsDir: path5__default.join(projectRoot, ".wrongstack", "skills"),
10445
+ projectSkillsDir: path17.join(projectRoot, ".wrongstack", "skills"),
9948
10446
  globalSkillsDir: deps2.wpaths.globalSkills
9949
10447
  };
9950
10448
  }
@@ -10399,6 +10897,7 @@ function createMessageDispatcher(opts) {
10399
10897
  break;
10400
10898
  }
10401
10899
  case "prefs.update": {
10900
+ void ws;
10402
10901
  throw new Error("handlePrefsRoute did not claim prefs.update \u2014 check chain order");
10403
10902
  }
10404
10903
  case "prefs.get": {
@@ -10412,6 +10911,11 @@ function createMessageDispatcher(opts) {
10412
10911
  }
10413
10912
  };
10414
10913
  }
10914
+
10915
+ // src/server/pref-helpers.ts
10916
+ import { atomicWrite as atomicWrite6 } from "@wrongstack/core/utils";
10917
+ import { decryptConfigSecrets as decryptConfigSecrets2, encryptConfigSecrets as encryptConfigSecrets2 } from "@wrongstack/core/security";
10918
+ import * as fs13 from "node:fs/promises";
10415
10919
  var PREF_KEYS = [
10416
10920
  "autonomy",
10417
10921
  "autonomyDelayMs",
@@ -10471,7 +10975,7 @@ async function updateGlobalConfig(deps2, holder, mutate, errorLabel) {
10471
10975
  const write = async () => {
10472
10976
  let raw;
10473
10977
  try {
10474
- raw = await fs4.readFile(globalConfigPath, "utf8");
10978
+ raw = await fs13.readFile(globalConfigPath, "utf8");
10475
10979
  } catch {
10476
10980
  raw = "{}";
10477
10981
  }
@@ -10482,10 +10986,10 @@ async function updateGlobalConfig(deps2, holder, mutate, errorLabel) {
10482
10986
  logger.warn(`${errorLabel}: refusing to overwrite corrupt config at ${globalConfigPath}`);
10483
10987
  return;
10484
10988
  }
10485
- const decrypted = decryptConfigSecrets(parsed, vault);
10989
+ const decrypted = decryptConfigSecrets2(parsed, vault);
10486
10990
  mutate(decrypted);
10487
- const encrypted = encryptConfigSecrets(decrypted, vault);
10488
- await atomicWrite$1(globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
10991
+ const encrypted = encryptConfigSecrets2(decrypted, vault);
10992
+ await atomicWrite6(globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
10489
10993
  };
10490
10994
  const next = holder.lock.then(write);
10491
10995
  holder.lock = next.then(
@@ -10647,13 +11151,18 @@ async function persistPrefsToConfig(deps2, holder, payload) {
10647
11151
  }
10648
11152
  }, "prefs");
10649
11153
  }
11154
+
11155
+ // src/server/projects-manifest.ts
11156
+ import * as fs14 from "node:fs/promises";
11157
+ import * as path18 from "node:path";
11158
+ import { projectSlug } from "@wrongstack/core";
10650
11159
  function projectsJsonPath(globalConfigPath) {
10651
- const base = path5.dirname(globalConfigPath);
10652
- return path5.join(base, "projects.json");
11160
+ const base = path18.dirname(globalConfigPath);
11161
+ return path18.join(base, "projects.json");
10653
11162
  }
10654
11163
  async function loadManifest(globalConfigPath) {
10655
11164
  try {
10656
- const raw = await fs4.readFile(projectsJsonPath(globalConfigPath), "utf8");
11165
+ const raw = await fs14.readFile(projectsJsonPath(globalConfigPath), "utf8");
10657
11166
  const parsed = JSON.parse(raw);
10658
11167
  return { projects: parsed.projects ?? [] };
10659
11168
  } catch {
@@ -10662,18 +11171,26 @@ async function loadManifest(globalConfigPath) {
10662
11171
  }
10663
11172
  async function saveManifest(manifest, globalConfigPath) {
10664
11173
  const file = projectsJsonPath(globalConfigPath);
10665
- await fs4.mkdir(path5.dirname(file), { recursive: true });
10666
- await fs4.writeFile(file, JSON.stringify(manifest, null, 2), "utf8");
11174
+ await fs14.mkdir(path18.dirname(file), { recursive: true });
11175
+ await fs14.writeFile(file, JSON.stringify(manifest, null, 2), "utf8");
10667
11176
  }
10668
11177
  function generateProjectSlug(rootPath) {
10669
11178
  return projectSlug(rootPath);
10670
11179
  }
10671
11180
  async function ensureProjectDataDir(slug, globalConfigPath) {
10672
- const base = path5.dirname(globalConfigPath);
10673
- const dir = path5.join(base, "projects", slug);
10674
- await fs4.mkdir(dir, { recursive: true });
11181
+ const base = path18.dirname(globalConfigPath);
11182
+ const dir = path18.join(base, "projects", slug);
11183
+ await fs14.mkdir(dir, { recursive: true });
10675
11184
  return dir;
10676
11185
  }
11186
+
11187
+ // src/server/provider-handlers.ts
11188
+ import { DefaultSecretScrubber } from "@wrongstack/core";
11189
+ import {
11190
+ beginOAuthLogin
11191
+ } from "@wrongstack/providers/oauth";
11192
+ import { probeLocalLlm } from "@wrongstack/runtime/probe";
11193
+ import { toErrorMessage as toErrorMessage9 } from "@wrongstack/core/utils";
10677
11194
  function projectSavedProviders(providers) {
10678
11195
  return Object.entries(providers).map(([id, cfg]) => {
10679
11196
  const keys = normalizeKeys(cfg);
@@ -10704,7 +11221,7 @@ function createProviderHandlers(deps2) {
10704
11221
  }
10705
11222
  async function saveConfigProviders(providers) {
10706
11223
  const next = configWriteLock.then(() => saveProviders(globalConfigPath, vault, providers)).catch((err) => {
10707
- const msg = toErrorMessage(err);
11224
+ const msg = toErrorMessage9(err);
10708
11225
  console.error(JSON.stringify({
10709
11226
  level: "error",
10710
11227
  event: "webui.provider_save_failed",
@@ -10976,10 +11493,23 @@ function createProviderHandlers(deps2) {
10976
11493
  loadConfigProviders
10977
11494
  };
10978
11495
  }
11496
+
11497
+ // src/server/routes.ts
11498
+ import path21 from "node:path";
11499
+ import {
11500
+ enhanceUserPrompt,
11501
+ gatedEnhancerReasoning,
11502
+ recentTextTurns,
11503
+ resolveProviderModelList
11504
+ } from "@wrongstack/core";
11505
+ import { makeProviderFromConfig as makeProviderFromConfig2 } from "@wrongstack/providers";
11506
+
11507
+ // src/server/mailbox-handlers.ts
11508
+ import { GlobalMailbox as GlobalMailbox3, resolveProjectDir as resolveProjectDir2 } from "@wrongstack/core";
10979
11509
  async function handleMailboxMessages(ws, deps2, payload) {
10980
11510
  try {
10981
- const dir = resolveProjectDir(deps2.projectRoot, deps2.globalRoot);
10982
- const mb = new GlobalMailbox(dir);
11511
+ const dir = resolveProjectDir2(deps2.projectRoot, deps2.globalRoot);
11512
+ const mb = new GlobalMailbox3(dir);
10983
11513
  const limit = payload?.limit ?? 30;
10984
11514
  const unreadForAgent = payload?.unreadOnly === true && payload.agentId !== void 0;
10985
11515
  const messages = await mb.query({
@@ -11019,8 +11549,8 @@ async function handleMailboxMessages(ws, deps2, payload) {
11019
11549
  }
11020
11550
  async function handleMailboxAgents(ws, deps2, payload) {
11021
11551
  try {
11022
- const dir = resolveProjectDir(deps2.projectRoot, deps2.globalRoot);
11023
- const mb = new GlobalMailbox(dir);
11552
+ const dir = resolveProjectDir2(deps2.projectRoot, deps2.globalRoot);
11553
+ const mb = new GlobalMailbox3(dir);
11024
11554
  const agents = payload?.onlineOnly ? await mb.getOnlineAgents() : await mb.getAgentStatuses();
11025
11555
  send(ws, {
11026
11556
  type: "mailbox.agents",
@@ -11048,8 +11578,8 @@ async function handleMailboxAgents(ws, deps2, payload) {
11048
11578
  }
11049
11579
  async function handleMailboxClear(ws, deps2) {
11050
11580
  try {
11051
- const dir = resolveProjectDir(deps2.projectRoot, deps2.globalRoot);
11052
- const mb = new GlobalMailbox(dir);
11581
+ const dir = resolveProjectDir2(deps2.projectRoot, deps2.globalRoot);
11582
+ const mb = new GlobalMailbox3(dir);
11053
11583
  await mb.clearAll();
11054
11584
  send(ws, { type: "mailbox.cleared", payload: {} });
11055
11585
  } catch (err) {
@@ -11058,14 +11588,21 @@ async function handleMailboxClear(ws, deps2) {
11058
11588
  }
11059
11589
  async function handleMailboxPurge(ws, deps2, opts) {
11060
11590
  try {
11061
- const dir = resolveProjectDir(deps2.projectRoot, deps2.globalRoot);
11062
- const mb = new GlobalMailbox(dir);
11591
+ const dir = resolveProjectDir2(deps2.projectRoot, deps2.globalRoot);
11592
+ const mb = new GlobalMailbox3(dir);
11063
11593
  const result = await mb.purgeStale(opts);
11064
11594
  send(ws, { type: "mailbox.purged", payload: result });
11065
11595
  } catch (err) {
11066
11596
  send(ws, { type: "mailbox.purged", payload: { error: errMessage(err) } });
11067
11597
  }
11068
11598
  }
11599
+
11600
+ // src/server/mode-handlers.ts
11601
+ import {
11602
+ DefaultSystemPromptBuilder as DefaultSystemPromptBuilder2,
11603
+ resolveWstackPaths as resolveWstackPaths2,
11604
+ ToolValidationError as ToolValidationError5
11605
+ } from "@wrongstack/core";
11069
11606
  function createModeHandlers(ctx) {
11070
11607
  return {
11071
11608
  listModes: async (ws) => {
@@ -11108,14 +11645,14 @@ function createModeHandlers(ctx) {
11108
11645
  } else {
11109
11646
  const found = await ctx.modeStore.getMode(id);
11110
11647
  if (!found) {
11111
- throw new ToolValidationError({ message: `Unknown mode "${id}"`, field: "modeId" });
11648
+ throw new ToolValidationError5({ message: `Unknown mode "${id}"`, field: "modeId" });
11112
11649
  }
11113
11650
  await ctx.modeStore.setActiveMode(id);
11114
11651
  }
11115
11652
  ctx.setModeId(id);
11116
11653
  const modePrompt = id === "default" ? "" : (await ctx.modeStore.getMode(id))?.prompt ?? "";
11117
- const paths = resolveWstackPaths$1({ projectRoot: ctx.projectRoot, globalRoot: ctx.globalRoot });
11118
- const freshBuilder = new DefaultSystemPromptBuilder({
11654
+ const paths = resolveWstackPaths2({ projectRoot: ctx.projectRoot, globalRoot: ctx.globalRoot });
11655
+ const freshBuilder = new DefaultSystemPromptBuilder2({
11119
11656
  memoryStore: ctx.memoryStore,
11120
11657
  skillLoader: ctx.skillLoader,
11121
11658
  modeStore: ctx.modeStore,
@@ -11145,6 +11682,9 @@ function createModeHandlers(ctx) {
11145
11682
  }
11146
11683
  };
11147
11684
  }
11685
+
11686
+ // src/server/project-handlers.ts
11687
+ import * as path19 from "node:path";
11148
11688
  function createProjectHandlers(ctx) {
11149
11689
  return {
11150
11690
  listProjects: async (ws) => {
@@ -11170,7 +11710,7 @@ function createProjectHandlers(ctx) {
11170
11710
  selectProject: async (ws, msg) => {
11171
11711
  const payload = msg.payload;
11172
11712
  const root = typeof payload?.root === "string" ? payload.root : "";
11173
- const name2 = typeof payload?.name === "string" ? payload.name : root ? path5.basename(root) : "";
11713
+ const name2 = typeof payload?.name === "string" ? payload.name : root ? path19.basename(root) : "";
11174
11714
  send(ws, {
11175
11715
  type: "projects.selected",
11176
11716
  payload: {
@@ -11203,6 +11743,14 @@ function createProjectHandlers(ctx) {
11203
11743
  }
11204
11744
  };
11205
11745
  }
11746
+
11747
+ // src/server/session-handlers.ts
11748
+ import * as path20 from "node:path";
11749
+ import {
11750
+ DEFAULT_CONTEXT_WINDOW_MODE_ID,
11751
+ repairToolUseAdjacency,
11752
+ resolveContextWindowPolicy as resolveContextWindowPolicy3
11753
+ } from "@wrongstack/core";
11206
11754
  function createSessionHandlers(ctx) {
11207
11755
  const currentSessionId = () => ctx.getSession().id;
11208
11756
  const sessionPayload2 = (payload) => {
@@ -11356,7 +11904,7 @@ function createSessionHandlers(ctx) {
11356
11904
  return;
11357
11905
  }
11358
11906
  const { id } = parsed.value;
11359
- let policy = resolveContextWindowPolicy({}, id);
11907
+ let policy = resolveContextWindowPolicy3({}, id);
11360
11908
  if (policy.id !== id) {
11361
11909
  const customModes = ctx.customModeStore.list().filter((m) => m.custom === true);
11362
11910
  const custom = customModes.find((m) => m.id === id);
@@ -11428,7 +11976,7 @@ function createSessionHandlers(ctx) {
11428
11976
  const { id } = parsed.value;
11429
11977
  if (String(ctx.context.meta["contextWindowMode"] ?? "") === id) {
11430
11978
  ctx.context.meta["contextWindowMode"] = DEFAULT_CONTEXT_WINDOW_MODE_ID;
11431
- ctx.context.meta["contextWindowPolicy"] = resolveContextWindowPolicy({}, DEFAULT_CONTEXT_WINDOW_MODE_ID);
11979
+ ctx.context.meta["contextWindowPolicy"] = resolveContextWindowPolicy3({}, DEFAULT_CONTEXT_WINDOW_MODE_ID);
11432
11980
  }
11433
11981
  const result = ctx.customModeStore.remove(id);
11434
11982
  sendResult(ws, result.ok, result.error ?? `Mode "${id}" deleted`);
@@ -11548,10 +12096,10 @@ function createSessionHandlers(ctx) {
11548
12096
  listCheckpoints: async (ws, msg) => {
11549
12097
  if (!ensureCurrentSession(ws, msg, "session.checkpoints")) return;
11550
12098
  try {
11551
- const { DefaultSessionRewinder } = await import('@wrongstack/core');
12099
+ const { DefaultSessionRewinder } = await import("@wrongstack/core");
11552
12100
  const projectRoot = ctx.getProjectRoot();
11553
12101
  const rewinder = new DefaultSessionRewinder(
11554
- path5.join(projectRoot, ".wrongstack", "sessions"),
12102
+ path20.join(projectRoot, ".wrongstack", "sessions"),
11555
12103
  projectRoot
11556
12104
  );
11557
12105
  const checkpoints = await rewinder.listCheckpoints(ctx.getSession().id);
@@ -11564,10 +12112,10 @@ function createSessionHandlers(ctx) {
11564
12112
  if (!ensureCurrentSession(ws, msg, "session.rewind")) return;
11565
12113
  const { checkpointIndex } = msg.payload;
11566
12114
  try {
11567
- const { DefaultSessionRewinder } = await import('@wrongstack/core');
12115
+ const { DefaultSessionRewinder } = await import("@wrongstack/core");
11568
12116
  const projectRoot = ctx.getProjectRoot();
11569
12117
  const rewinder = new DefaultSessionRewinder(
11570
- path5.join(projectRoot, ".wrongstack", "sessions"),
12118
+ path20.join(projectRoot, ".wrongstack", "sessions"),
11571
12119
  projectRoot
11572
12120
  );
11573
12121
  await rewinder.rewindToCheckpoint(ctx.getSession().id, checkpointIndex);
@@ -11652,11 +12200,13 @@ function buildRoutes(state, deps2, cb) {
11652
12200
  const saved = await providerHandlers.loadConfigProviders();
11653
12201
  const cfg = saved[providerId];
11654
12202
  const provider = await resolveProviderCatalogForModels(deps2.modelsRegistry, providerId, cfg);
12203
+ const siblingId = SIBLING_CATALOG[providerId];
12204
+ const siblingCatalog = siblingId && siblingId !== providerId ? await deps2.modelsRegistry.getProvider(siblingId).catch(() => void 0) : void 0;
11655
12205
  const models = await enrichProviderModelDescriptors(
11656
12206
  deps2.modelsRegistry,
11657
12207
  providerId,
11658
12208
  cfg,
11659
- resolveProviderModelList(cfg?.models, provider, cfg?.type ?? providerId)
12209
+ resolveProviderModelList(cfg?.models, provider, cfg?.type ?? providerId, siblingCatalog)
11660
12210
  );
11661
12211
  send(ws, {
11662
12212
  type: "provider.models",
@@ -11682,7 +12232,7 @@ function buildRoutes(state, deps2, cb) {
11682
12232
  const providerCfg = newCfg.providers?.[newProvider] ?? {
11683
12233
  type: newProvider
11684
12234
  };
11685
- const newProv = deps2.providerRegistry.has(newProvider) ? deps2.providerRegistry.create({ ...providerCfg, type: newProvider }) : makeProviderFromConfig(newProvider, providerCfg);
12235
+ const newProv = deps2.providerRegistry.has(newProvider) ? deps2.providerRegistry.create({ ...providerCfg, type: newProvider }) : makeProviderFromConfig2(newProvider, providerCfg);
11686
12236
  deps2.context.provider = newProv;
11687
12237
  await cb.updateAutoCompactionMaxContext(newProv, newProvider, providerCfg);
11688
12238
  await cb.updateGlobalConfig((config) => {
@@ -11925,7 +12475,7 @@ function buildRoutes(state, deps2, cb) {
11925
12475
  }
11926
12476
  return handleMailboxMessages(
11927
12477
  ws,
11928
- { projectRoot: state.getProjectRoot(), globalRoot: path5__default.dirname(deps2.globalConfigPath) },
12478
+ { projectRoot: state.getProjectRoot(), globalRoot: path21.dirname(deps2.globalConfigPath) },
11929
12479
  parsed.value
11930
12480
  );
11931
12481
  },
@@ -11937,13 +12487,13 @@ function buildRoutes(state, deps2, cb) {
11937
12487
  }
11938
12488
  return handleMailboxAgents(
11939
12489
  ws,
11940
- { projectRoot: state.getProjectRoot(), globalRoot: path5__default.dirname(deps2.globalConfigPath) },
12490
+ { projectRoot: state.getProjectRoot(), globalRoot: path21.dirname(deps2.globalConfigPath) },
11941
12491
  parsed.value
11942
12492
  );
11943
12493
  },
11944
12494
  clear: (ws) => handleMailboxClear(ws, {
11945
12495
  projectRoot: state.getProjectRoot(),
11946
- globalRoot: path5__default.dirname(deps2.globalConfigPath)
12496
+ globalRoot: path21.dirname(deps2.globalConfigPath)
11947
12497
  }),
11948
12498
  purge: (ws, msg) => {
11949
12499
  const parsed = validateMailboxPurgePayload(msg.payload);
@@ -11953,7 +12503,7 @@ function buildRoutes(state, deps2, cb) {
11953
12503
  }
11954
12504
  return handleMailboxPurge(
11955
12505
  ws,
11956
- { projectRoot: state.getProjectRoot(), globalRoot: path5__default.dirname(deps2.globalConfigPath) },
12506
+ { projectRoot: state.getProjectRoot(), globalRoot: path21.dirname(deps2.globalConfigPath) },
11957
12507
  parsed.value
11958
12508
  );
11959
12509
  }
@@ -12061,7 +12611,7 @@ async function startWebUI(opts = {}) {
12061
12611
  const updateGlobalConfig2 = async (mutate, errorLabel) => updateGlobalConfig(prefHelperDeps, configWriteLock, mutate, errorLabel);
12062
12612
  console.log("[WebUI] Config loaded:", config.provider ?? "(none)", "/", config.model ?? "(none)");
12063
12613
  if (!config.provider && config.providers && typeof config.providers === "object" && config.providers !== null && !Array.isArray(config.providers) && Object.keys(config.providers).length > 0) {
12064
- const firstKey = expectDefined(Object.keys(config.providers)[0]);
12614
+ const firstKey = expectDefined3(Object.keys(config.providers)[0]);
12065
12615
  config = patchConfig(config, { provider: firstKey });
12066
12616
  console.log("[WebUI] No active provider \u2014 auto-selected:", firstKey);
12067
12617
  }
@@ -12161,7 +12711,7 @@ async function startWebUI(opts = {}) {
12161
12711
  getProjectRoot: () => projectRoot,
12162
12712
  getWorkingDir: () => workingDir,
12163
12713
  getModeId: () => modeId,
12164
- getContextMode: () => String(context.meta["contextWindowMode"] ?? DEFAULT_CONTEXT_WINDOW_MODE_ID),
12714
+ getContextMode: () => String(context.meta["contextWindowMode"] ?? DEFAULT_CONTEXT_WINDOW_MODE_ID2),
12165
12715
  getNeedsSetup: () => needsSetup,
12166
12716
  modelsRegistry
12167
12717
  });
@@ -12204,21 +12754,21 @@ async function startWebUI(opts = {}) {
12204
12754
  wpaths
12205
12755
  }, watcherMetricsRef);
12206
12756
  async function touchProjectEntry(root, workDir) {
12207
- const resolved = path5.resolve(root);
12757
+ const resolved = path22.resolve(root);
12208
12758
  const manifest = await loadManifest(globalConfigPath);
12209
12759
  const now = (/* @__PURE__ */ new Date()).toISOString();
12210
- const existing = manifest.projects.find((p) => path5.resolve(p.root) === resolved);
12760
+ const existing = manifest.projects.find((p) => path22.resolve(p.root) === resolved);
12211
12761
  if (existing) {
12212
12762
  existing.lastSeen = now;
12213
- if (workDir) existing.lastWorkingDir = path5.resolve(workDir);
12763
+ if (workDir) existing.lastWorkingDir = path22.resolve(workDir);
12214
12764
  } else {
12215
12765
  manifest.projects.push({
12216
- name: path5.basename(resolved),
12766
+ name: path22.basename(resolved),
12217
12767
  root: resolved,
12218
12768
  slug: generateProjectSlug(resolved),
12219
12769
  createdAt: now,
12220
12770
  lastSeen: now,
12221
- lastWorkingDir: workDir ? path5.resolve(workDir) : void 0
12771
+ lastWorkingDir: workDir ? path22.resolve(workDir) : void 0
12222
12772
  });
12223
12773
  }
12224
12774
  await saveManifest(manifest, globalConfigPath);
@@ -12363,13 +12913,13 @@ async function startWebUI(opts = {}) {
12363
12913
  ...snapshot.apiKey !== void 0 ? { apiKey: snapshot.apiKey } : {},
12364
12914
  ...snapshot.baseUrl !== void 0 ? { baseUrl: snapshot.baseUrl } : {}
12365
12915
  };
12366
- const newProv = deps2.providerRegistry.has(activeId) ? deps2.providerRegistry.create({ ...providerCfg, type: activeId }) : makeProviderFromConfig(activeId, { ...providerCfg, type: activeId });
12916
+ const newProv = deps2.providerRegistry.has(activeId) ? deps2.providerRegistry.create({ ...providerCfg, type: activeId }) : makeProviderFromConfig3(activeId, { ...providerCfg, type: activeId });
12367
12917
  deps2.context.provider = newProv;
12368
12918
  void updateAutoCompactionMaxContext(newProv).catch(() => void 0);
12369
12919
  console.log(`[WebUI] Provider credentials reloaded from config.json (${activeId})`);
12370
12920
  } catch (err) {
12371
12921
  console.warn(
12372
- `[WebUI] Credential hot-reload failed for ${activeId}: ${toErrorMessage(err)}`
12922
+ `[WebUI] Credential hot-reload failed for ${activeId}: ${toErrorMessage10(err)}`
12373
12923
  );
12374
12924
  }
12375
12925
  },
@@ -12436,20 +12986,33 @@ async function startWebUI(opts = {}) {
12436
12986
  },
12437
12987
  clients: () => clients.keys(),
12438
12988
  servers: [httpServer, wssPrimary, ...wssSecondary ? [wssSecondary] : []],
12439
- onShutdown: () => {
12989
+ onShutdown: async () => {
12440
12990
  credentialWatcherClose?.();
12441
12991
  brainMonitor.stop();
12442
- void mcpRegistry.stopAll().catch(() => void 0);
12992
+ await mcpRegistry.stopAll().catch(() => void 0);
12443
12993
  eventArming.getDispose()?.();
12444
12994
  if (eternalSubscription) {
12445
12995
  eternalSubscription.dispose();
12446
12996
  eternalSubscription = null;
12447
12997
  }
12448
12998
  codebaseIndexing.dispose();
12449
- return unregisterInstance(process.pid, path5.dirname(globalConfigPath));
12999
+ if (config.superMemory?.enabled !== false && config.superMemory?.hygiene?.autoAfterSession !== false) {
13000
+ const candidate = memoryStore;
13001
+ await candidate.hygiene?.({
13002
+ retentionDays: config.superMemory?.hygiene?.retentionDays,
13003
+ archiveLowConfidenceAfterDays: config.superMemory?.hygiene?.archiveLowConfidenceAfterDays
13004
+ }).catch((err) => logger.warn(`super-memory session hygiene failed: ${toErrorMessage10(err)}`));
13005
+ }
13006
+ await unregisterInstance(process.pid, path22.dirname(globalConfigPath));
12450
13007
  }
12451
13008
  });
12452
13009
  }
13010
+
13011
+ // src/server/provider-store.ts
13012
+ import { expectDefined as expectDefined4 } from "@wrongstack/core";
13013
+ import * as fs15 from "node:fs/promises";
13014
+ import { decryptConfigSecrets as decryptConfigSecrets3, encryptConfigSecrets as encryptConfigSecrets3 } from "@wrongstack/core/security";
13015
+ import { atomicWrite as atomicWrite7 } from "@wrongstack/core";
12453
13016
  function createConfigWriteLock() {
12454
13017
  let lock = Promise.resolve();
12455
13018
  return {
@@ -12471,10 +13034,10 @@ function createProviderStore(deps2) {
12471
13034
  const configWriteLock = createConfigWriteLock();
12472
13035
  async function loadSavedProviders2() {
12473
13036
  try {
12474
- const raw = await fs4.readFile(globalConfigPath, "utf8");
13037
+ const raw = await fs15.readFile(globalConfigPath, "utf8");
12475
13038
  const parsed = JSON.parse(raw);
12476
13039
  if (!parsed.providers) return {};
12477
- return decryptConfigSecrets(parsed.providers, vault);
13040
+ return decryptConfigSecrets3(parsed.providers, vault);
12478
13041
  } catch {
12479
13042
  return {};
12480
13043
  }
@@ -12485,14 +13048,14 @@ function createProviderStore(deps2) {
12485
13048
  await prev;
12486
13049
  let parsed;
12487
13050
  try {
12488
- const raw = await fs4.readFile(globalConfigPath, "utf8");
13051
+ const raw = await fs15.readFile(globalConfigPath, "utf8");
12489
13052
  parsed = JSON.parse(raw);
12490
13053
  } catch {
12491
13054
  parsed = {};
12492
13055
  }
12493
13056
  parsed["providers"] = providers;
12494
- const encrypted = encryptConfigSecrets(parsed, vault);
12495
- await atomicWrite(globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
13057
+ const encrypted = encryptConfigSecrets3(parsed, vault);
13058
+ await atomicWrite7(globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
12496
13059
  } finally {
12497
13060
  release();
12498
13061
  }
@@ -12514,7 +13077,7 @@ function createProviderStore(deps2) {
12514
13077
  return;
12515
13078
  }
12516
13079
  cfg.apiKeys = keys;
12517
- const active = keys.find((k) => k.label === cfg.activeKey) ?? expectDefined(keys[0]);
13080
+ const active = keys.find((k) => k.label === cfg.activeKey) ?? expectDefined4(keys[0]);
12518
13081
  delete cfg.apiKey;
12519
13082
  if (!cfg.activeKey || !keys.some((k) => k.label === cfg.activeKey)) {
12520
13083
  cfg.activeKey = active.label;
@@ -12533,7 +13096,186 @@ function createProviderStore(deps2) {
12533
13096
  maskedKey: maskedKey2
12534
13097
  };
12535
13098
  }
12536
-
12537
- export { AutoPhaseWebSocketHandler, CollaborationWebSocketHandler, SKIP_DIRS, SddBoardWebSocketHandler, SddWizardWebSocketHandler, SpecsWebSocketHandler, TerminalWebSocketHandler, WorktreeWebSocketHandler, addProvider, bootConfig, broadcast, browserOpenCommand, buildCspHeader, buildSddWizardDeps, buildWebUIAccessUrl, clearAnalyticsBuffer, computeUsageCost, createConfigWriteLock, createCustomModeStore, createEternalSubscription, createHttpServer, createProviderConfigIO, createProviderHandlers, createProviderStore, createShutdown, createToolLspCompletionSource, decodeSessionId, defaultBaseDir, deleteKey, ensureProjectDataDir, envFlag, errMessage, estimateContextBreakdown, estimateTokens, extractToken, extractTokenFromCookie, findFreePort, formatInstances, generateAuthToken, getAnalyticsBuffer, getCostRates, handleApiAnalyticsGet, handleApiAnalyticsPost, handleApiAnalyticsSummary, handleAutoPhaseRoute, handleBrainRoute, handleCompletionRequest, handleDesignList, handleDesignMaterialize, handleDesignSet, handleDesignState, handleDesignUse, handleDesignVerify, handleFilesList, handleFilesRead, handleFilesTree, handleFilesWrite, handleGitChanges, handleGitDiff, handleGitInfo, handleGoalGet, handleMailboxMessages, handleMailboxRoute, handleMcpAdd, handleMcpDisable, handleMcpDiscover, handleMcpEnable, handleMcpList, handleMcpRemove, handleMcpRestart, handleMcpRoute, handleMcpSleep, handleMcpUpdate, handleMcpWake, handleMemoryForget, handleMemoryList, handleMemoryRemember, handleModeRoute, handlePrefsRoute, handleProcessKill, handleProcessKillAll, handleProcessList, handleProjectRoute, handlePromptsContent, handlePromptsCreate, handlePromptsFavorite, handlePromptsList, handlePromptsRecent, handlePromptsSearch, handlePromptsUsed, handleProviderRoute, handleSddBoardRoute, handleSddWizardRoute, handleSessionRoute, handleShellGitRoute, handleShellOpen, handleSkillsContent, handleSkillsCreate, handleSkillsEdit, handleSkillsExport, handleSkillsInstall, handleSkillsList, handleSkillsUninstall, handleSkillsUpdate, handleSpecsRoute, handleWorklistMessage, hostForBrowserUrl, hostHeaderOk, injectWsConfig, injectWsPort, isHiddenEntry, isInsideDist, isLoopbackBind, isLoopbackHostname, isPathInside, isPidAlive, isPortFree, isWildcardBind, listInstances, loadManifest, loadSavedProviders, maskedKey, messagePreview, messageTokens, normalizeKeys, openBrowser, patchConfig, persistPrefsToConfig, projectSavedProviders, projectsJsonPath, rankFiles, registerInstance, registerShutdownHandlers, registryPath, removeProvider, resolveAllPendingConfirms, resolveAuthToken, resolveProviderCatalogForModels, resolveProviderModelMetadata, resolveWorkingDirInsideProject, resolveYoloEligiblePendingConfirms, saveManifest, saveProviders, send, sendResult, setActiveKey, setupEvents, setupWebUICodebaseIndexing, startWebUI, statusProjectHashFromWatchFilename, stringifyContent, tokenMatches, unregisterInstance, upsertKey, validateAutonomySwitchPayload, validateBrainAskPayload, validateBrainRiskPayload, validateContextModeCreatePayload, validateContextModeDeletePayload, validateContextModeSwitchPayload, validateContextModeUpdatePayload, validateGitDiffPayload, validateMailboxAgentsPayload, validateMailboxMessagesPayload, validateMailboxPurgePayload, validateModeSwitchPayload, validateModelSwitchPayload, validatePlanTemplateUsePayload, validatePrefsUpdatePayload, validateProcessKillPayload, validateProjectsAddPayload, validateProjectsSelectPayload, validateShellOpenPayload, validateSkillsCreatePayload, validateSkillsEditPayload, validateWorkingDirSetPayload, verifyClient, writeKeysBack };
13099
+ export {
13100
+ AutoPhaseWebSocketHandler,
13101
+ CollaborationWebSocketHandler,
13102
+ SKIP_DIRS,
13103
+ SddBoardWebSocketHandler,
13104
+ SddWizardWebSocketHandler,
13105
+ SpecsWebSocketHandler,
13106
+ TerminalWebSocketHandler,
13107
+ WorktreeWebSocketHandler,
13108
+ addProvider,
13109
+ bootConfig,
13110
+ broadcast,
13111
+ browserOpenCommand,
13112
+ buildCspHeader,
13113
+ buildSddWizardDeps,
13114
+ buildWebUIAccessUrl,
13115
+ clearAnalyticsBuffer,
13116
+ computeUsageCost,
13117
+ createConfigWriteLock,
13118
+ createCustomModeStore,
13119
+ createEternalSubscription,
13120
+ createHttpServer,
13121
+ createProviderConfigIO,
13122
+ createProviderHandlers,
13123
+ createProviderStore,
13124
+ createShutdown,
13125
+ createToolLspCompletionSource,
13126
+ createZipBuffer,
13127
+ decodeSessionId,
13128
+ defaultBaseDir,
13129
+ deleteKey,
13130
+ ensureProjectDataDir,
13131
+ envFlag,
13132
+ errMessage,
13133
+ estimateContextBreakdown,
13134
+ estimateTokens,
13135
+ extractToken,
13136
+ extractTokenFromCookie,
13137
+ findFreePort,
13138
+ formatInstances,
13139
+ generateAuthToken,
13140
+ getAnalyticsBuffer,
13141
+ getCostRates,
13142
+ handleApiAnalyticsGet,
13143
+ handleApiAnalyticsPost,
13144
+ handleApiAnalyticsSummary,
13145
+ handleAutoPhaseRoute,
13146
+ handleBrainRoute,
13147
+ handleCompletionRequest,
13148
+ handleDesignList,
13149
+ handleDesignMaterialize,
13150
+ handleDesignSet,
13151
+ handleDesignState,
13152
+ handleDesignUse,
13153
+ handleDesignVerify,
13154
+ handleFilesList,
13155
+ handleFilesRead,
13156
+ handleFilesTree,
13157
+ handleFilesWrite,
13158
+ handleGitChanges,
13159
+ handleGitDiff,
13160
+ handleGitInfo,
13161
+ handleGoalGet,
13162
+ handleMailboxMessages,
13163
+ handleMailboxRoute,
13164
+ handleMcpAdd,
13165
+ handleMcpDisable,
13166
+ handleMcpDiscover,
13167
+ handleMcpEnable,
13168
+ handleMcpList,
13169
+ handleMcpRemove,
13170
+ handleMcpRestart,
13171
+ handleMcpRoute,
13172
+ handleMcpSleep,
13173
+ handleMcpUpdate,
13174
+ handleMcpWake,
13175
+ handleMemoryForget,
13176
+ handleMemoryList,
13177
+ handleMemoryRemember,
13178
+ handleModeRoute,
13179
+ handlePrefsRoute,
13180
+ handleProcessKill,
13181
+ handleProcessKillAll,
13182
+ handleProcessList,
13183
+ handleProjectRoute,
13184
+ handlePromptsContent,
13185
+ handlePromptsCreate,
13186
+ handlePromptsFavorite,
13187
+ handlePromptsList,
13188
+ handlePromptsRecent,
13189
+ handlePromptsSearch,
13190
+ handlePromptsUsed,
13191
+ handleProviderRoute,
13192
+ handleSddBoardRoute,
13193
+ handleSddWizardRoute,
13194
+ handleSessionRoute,
13195
+ handleShellGitRoute,
13196
+ handleShellOpen,
13197
+ handleSkillsContent,
13198
+ handleSkillsCreate,
13199
+ handleSkillsEdit,
13200
+ handleSkillsExport,
13201
+ handleSkillsInstall,
13202
+ handleSkillsList,
13203
+ handleSkillsUninstall,
13204
+ handleSkillsUpdate,
13205
+ handleSpecsRoute,
13206
+ handleWorklistMessage,
13207
+ hostForBrowserUrl,
13208
+ hostHeaderOk,
13209
+ injectWsConfig,
13210
+ injectWsPort,
13211
+ isHiddenEntry,
13212
+ isInsideDist,
13213
+ isLoopbackBind,
13214
+ isLoopbackHostname,
13215
+ isPathInside,
13216
+ isPidAlive,
13217
+ isPortFree,
13218
+ isWildcardBind,
13219
+ listInstances,
13220
+ loadManifest,
13221
+ loadSavedProviders,
13222
+ maskedKey,
13223
+ messagePreview,
13224
+ messageTokens,
13225
+ normalizeKeys,
13226
+ openBrowser,
13227
+ patchConfig,
13228
+ persistPrefsToConfig,
13229
+ projectSavedProviders,
13230
+ projectsJsonPath,
13231
+ rankFiles,
13232
+ readZipEntries,
13233
+ registerInstance,
13234
+ registerShutdownHandlers,
13235
+ registryPath,
13236
+ removeProvider,
13237
+ resolveAllPendingConfirms,
13238
+ resolveAuthToken,
13239
+ resolveProviderCatalogForModels,
13240
+ resolveProviderModelMetadata,
13241
+ resolveWorkingDirInsideProject,
13242
+ resolveYoloEligiblePendingConfirms,
13243
+ saveManifest,
13244
+ saveProviders,
13245
+ send,
13246
+ sendResult,
13247
+ setActiveKey,
13248
+ setupEvents,
13249
+ setupWebUICodebaseIndexing,
13250
+ startWebUI,
13251
+ statusProjectHashFromWatchFilename,
13252
+ stringifyContent,
13253
+ tokenMatches,
13254
+ unregisterInstance,
13255
+ upsertKey,
13256
+ validateAutonomySwitchPayload,
13257
+ validateBrainAskPayload,
13258
+ validateBrainRiskPayload,
13259
+ validateContextModeCreatePayload,
13260
+ validateContextModeDeletePayload,
13261
+ validateContextModeSwitchPayload,
13262
+ validateContextModeUpdatePayload,
13263
+ validateGitDiffPayload,
13264
+ validateMailboxAgentsPayload,
13265
+ validateMailboxMessagesPayload,
13266
+ validateMailboxPurgePayload,
13267
+ validateModeSwitchPayload,
13268
+ validateModelSwitchPayload,
13269
+ validatePlanTemplateUsePayload,
13270
+ validatePrefsUpdatePayload,
13271
+ validateProcessKillPayload,
13272
+ validateProjectsAddPayload,
13273
+ validateProjectsSelectPayload,
13274
+ validateShellOpenPayload,
13275
+ validateSkillsCreatePayload,
13276
+ validateSkillsEditPayload,
13277
+ validateWorkingDirSetPayload,
13278
+ verifyClient,
13279
+ writeKeysBack
13280
+ };
12538
13281
  //# sourceMappingURL=index.js.map
12539
- //# sourceMappingURL=index.js.map