@docyrus/docyrus 0.0.34 → 0.0.36

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 (66) hide show
  1. package/README.md +25 -0
  2. package/agent-loader.js +3 -2
  3. package/agent-loader.js.map +2 -2
  4. package/main.js +82162 -46093
  5. package/main.js.map +4 -4
  6. package/package.json +12 -3
  7. package/resources/chrome-tools/browser-content.js +46 -46
  8. package/resources/chrome-tools/browser-cookies.js +16 -16
  9. package/resources/chrome-tools/browser-eval.js +27 -27
  10. package/resources/chrome-tools/browser-hn-scraper.js +1 -1
  11. package/resources/chrome-tools/browser-nav.js +23 -23
  12. package/resources/chrome-tools/browser-pick.js +127 -127
  13. package/resources/chrome-tools/browser-screenshot.js +10 -10
  14. package/resources/chrome-tools/browser-start.js +38 -38
  15. package/resources/pi-agent/extensions/answer.ts +392 -384
  16. package/resources/pi-agent/extensions/context.ts +415 -415
  17. package/resources/pi-agent/extensions/control.ts +1287 -1287
  18. package/resources/pi-agent/extensions/diff.ts +171 -171
  19. package/resources/pi-agent/extensions/files.ts +155 -155
  20. package/resources/pi-agent/extensions/knowledge.ts +664 -0
  21. package/resources/pi-agent/extensions/loop.ts +375 -375
  22. package/resources/pi-agent/extensions/pi-bash-live-view/index.ts +1 -1
  23. package/resources/pi-agent/extensions/pi-bash-live-view/package.json +22 -22
  24. package/resources/pi-agent/extensions/pi-bash-live-view/pty-execute.ts +2 -2
  25. package/resources/pi-agent/extensions/pi-bash-live-view/pty-session.ts +2 -2
  26. package/resources/pi-agent/extensions/pi-bash-live-view/spawn-helper.ts +2 -2
  27. package/resources/pi-agent/extensions/pi-bash-live-view/terminal-emulator.ts +18 -18
  28. package/resources/pi-agent/extensions/pi-bash-live-view/truncate.ts +1 -1
  29. package/resources/pi-agent/extensions/pi-bash-live-view/widget.ts +4 -4
  30. package/resources/pi-agent/extensions/pi-custom-compaction/package.json +4 -4
  31. package/resources/pi-agent/extensions/pi-mcp-adapter/app-bridge.bundle.js +14 -14
  32. package/resources/pi-agent/extensions/pi-mcp-adapter/commands.ts +6 -6
  33. package/resources/pi-agent/extensions/pi-mcp-adapter/config.ts +9 -9
  34. package/resources/pi-agent/extensions/pi-mcp-adapter/consent-manager.ts +4 -4
  35. package/resources/pi-agent/extensions/pi-mcp-adapter/direct-tools.ts +13 -13
  36. package/resources/pi-agent/extensions/pi-mcp-adapter/glimpse-ui.ts +5 -5
  37. package/resources/pi-agent/extensions/pi-mcp-adapter/host-html-template.ts +13 -13
  38. package/resources/pi-agent/extensions/pi-mcp-adapter/index.ts +14 -14
  39. package/resources/pi-agent/extensions/pi-mcp-adapter/init.ts +17 -17
  40. package/resources/pi-agent/extensions/pi-mcp-adapter/lifecycle.ts +2 -2
  41. package/resources/pi-agent/extensions/pi-mcp-adapter/logger.ts +2 -2
  42. package/resources/pi-agent/extensions/pi-mcp-adapter/mcp-panel.ts +17 -17
  43. package/resources/pi-agent/extensions/pi-mcp-adapter/metadata-cache.ts +9 -9
  44. package/resources/pi-agent/extensions/pi-mcp-adapter/npx-resolver.ts +35 -35
  45. package/resources/pi-agent/extensions/pi-mcp-adapter/oauth-handler.ts +1 -1
  46. package/resources/pi-agent/extensions/pi-mcp-adapter/proxy-modes.ts +12 -12
  47. package/resources/pi-agent/extensions/pi-mcp-adapter/server-manager.ts +6 -6
  48. package/resources/pi-agent/extensions/pi-mcp-adapter/tool-metadata.ts +4 -4
  49. package/resources/pi-agent/extensions/pi-mcp-adapter/types.ts +2 -2
  50. package/resources/pi-agent/extensions/pi-mcp-adapter/ui-resource-handler.ts +6 -6
  51. package/resources/pi-agent/extensions/pi-mcp-adapter/ui-server.ts +17 -17
  52. package/resources/pi-agent/extensions/pi-mcp-adapter/ui-session.ts +22 -22
  53. package/resources/pi-agent/extensions/pi-mcp-adapter/utils.ts +2 -2
  54. package/resources/pi-agent/extensions/prompt-editor.ts +900 -900
  55. package/resources/pi-agent/extensions/prompt-url-widget.ts +122 -122
  56. package/resources/pi-agent/extensions/redraws.ts +14 -14
  57. package/resources/pi-agent/extensions/review.ts +1533 -1533
  58. package/resources/pi-agent/extensions/todos.ts +1735 -1735
  59. package/resources/pi-agent/extensions/tps.ts +40 -40
  60. package/resources/pi-agent/extensions/whimsical.ts +3 -3
  61. package/resources/pi-agent/prompts/agent-system.md +2 -0
  62. package/resources/pi-agent/prompts/coder-system.md +2 -0
  63. package/server-loader.js +82 -1
  64. package/server-loader.js.map +3 -3
  65. package/tui.mjs +2 -0
  66. package/tui.mjs.map +1 -1
@@ -44,12 +44,12 @@ export function getMetadataCachePath(): string {
44
44
  }
45
45
 
46
46
  export function loadMetadataCache(): MetadataCache | null {
47
- if (!existsSync(CACHE_PATH)) return null;
47
+ if (!existsSync(CACHE_PATH)) {return null;}
48
48
  try {
49
49
  const raw = JSON.parse(readFileSync(CACHE_PATH, "utf-8"));
50
- if (!raw || typeof raw !== "object") return null;
51
- if (raw.version !== CACHE_VERSION) return null;
52
- if (!raw.servers || typeof raw.servers !== "object") return null;
50
+ if (!raw || typeof raw !== "object") {return null;}
51
+ if (raw.version !== CACHE_VERSION) {return null;}
52
+ if (!raw.servers || typeof raw.servers !== "object") {return null;}
53
53
  return raw as MetadataCache;
54
54
  } catch {
55
55
  return null;
@@ -105,9 +105,9 @@ export function isServerCacheValid(
105
105
  definition: ServerEntry,
106
106
  maxAgeMs: number = CACHE_MAX_AGE_MS
107
107
  ): boolean {
108
- if (!entry || entry.configHash !== computeServerHash(definition)) return false;
109
- if (!entry.cachedAt || typeof entry.cachedAt !== "number") return false;
110
- if (maxAgeMs > 0 && Date.now() - entry.cachedAt > maxAgeMs) return false;
108
+ if (!entry || entry.configHash !== computeServerHash(definition)) {return false;}
109
+ if (!entry.cachedAt || typeof entry.cachedAt !== "number") {return false;}
110
+ if (maxAgeMs > 0 && Date.now() - entry.cachedAt > maxAgeMs) {return false;}
111
111
  return true;
112
112
  }
113
113
 
@@ -120,7 +120,7 @@ export function reconstructToolMetadata(
120
120
  const metadata: ToolMetadata[] = [];
121
121
 
122
122
  for (const tool of entry.tools ?? []) {
123
- if (!tool?.name) continue;
123
+ if (!tool?.name) {continue;}
124
124
  metadata.push({
125
125
  name: formatToolName(tool.name, serverName, prefix),
126
126
  originalName: tool.name,
@@ -133,7 +133,7 @@ export function reconstructToolMetadata(
133
133
 
134
134
  if (exposeResources !== false) {
135
135
  for (const resource of entry.resources ?? []) {
136
- if (!resource?.name || !resource?.uri) continue;
136
+ if (!resource?.name || !resource?.uri) {continue;}
137
137
  const baseName = `get_${resourceNameToToolName(resource.name)}`;
138
138
  metadata.push({
139
139
  name: formatToolName(baseName, serverName, prefix),
@@ -42,7 +42,7 @@ export async function resolveNpxBinary(
42
42
  ? parseNpmExecArgs(args)
43
43
  : null;
44
44
 
45
- if (!parsed) return null;
45
+ if (!parsed) {return null;}
46
46
 
47
47
  const cacheKey = JSON.stringify([command, ...args]);
48
48
  const cache = loadCache();
@@ -85,19 +85,19 @@ function parseNpxArgs(args: string[]): ParsedInvocation | null {
85
85
  positionals.push(arg);
86
86
  continue;
87
87
  }
88
- if (arg === "-y" || arg === "--yes") continue;
88
+ if (arg === "-y" || arg === "--yes") {continue;}
89
89
  if (arg === "-p" || arg === "--package") {
90
90
  const value = before[i + 1];
91
- if (!value || value.startsWith("-")) return null;
92
- if (!packageSpec) packageSpec = value;
91
+ if (!value || value.startsWith("-")) {return null;}
92
+ if (!packageSpec) {packageSpec = value;}
93
93
  sawPackageFlag = true;
94
94
  i++;
95
95
  continue;
96
96
  }
97
97
  if (arg.startsWith("--package=")) {
98
98
  const value = arg.slice("--package=".length);
99
- if (!value) return null;
100
- if (!packageSpec) packageSpec = value;
99
+ if (!value) {return null;}
100
+ if (!packageSpec) {packageSpec = value;}
101
101
  sawPackageFlag = true;
102
102
  continue;
103
103
  }
@@ -110,22 +110,22 @@ function parseNpxArgs(args: string[]): ParsedInvocation | null {
110
110
 
111
111
  if (sawPackageFlag) {
112
112
  const binName = positionals[0];
113
- if (!packageSpec || !binName) return null;
113
+ if (!packageSpec || !binName) {return null;}
114
114
  const extraArgs = positionals.slice(1).concat(after);
115
115
  return { packageSpec, binName, extraArgs };
116
116
  }
117
117
 
118
118
  const packagePositional = positionals[0];
119
- if (!packagePositional) return null;
119
+ if (!packagePositional) {return null;}
120
120
  const extraArgs = positionals.slice(1).concat(after);
121
121
  return { packageSpec: packagePositional, extraArgs };
122
122
  }
123
123
 
124
124
  function parseNpmExecArgs(args: string[]): ParsedInvocation | null {
125
- if (args[0] !== "exec") return null;
125
+ if (args[0] !== "exec") {return null;}
126
126
  const execArgs = args.slice(1);
127
127
  const separatorIndex = execArgs.indexOf("--");
128
- if (separatorIndex < 0) return null;
128
+ if (separatorIndex < 0) {return null;}
129
129
 
130
130
  const before = execArgs.slice(0, separatorIndex);
131
131
  const after = execArgs.slice(separatorIndex + 1);
@@ -133,18 +133,18 @@ function parseNpmExecArgs(args: string[]): ParsedInvocation | null {
133
133
  let packageSpec: string | undefined;
134
134
  for (let i = 0; i < before.length; i++) {
135
135
  const arg = before[i];
136
- if (arg === "-y" || arg === "--yes") continue;
136
+ if (arg === "-y" || arg === "--yes") {continue;}
137
137
  if (arg === "--package") {
138
138
  const value = before[i + 1];
139
- if (!value || value.startsWith("-")) return null;
140
- if (!packageSpec) packageSpec = value;
139
+ if (!value || value.startsWith("-")) {return null;}
140
+ if (!packageSpec) {packageSpec = value;}
141
141
  i++;
142
142
  continue;
143
143
  }
144
144
  if (arg.startsWith("--package=")) {
145
145
  const value = arg.slice("--package=".length);
146
- if (!value) return null;
147
- if (!packageSpec) packageSpec = value;
146
+ if (!value) {return null;}
147
+ if (!packageSpec) {packageSpec = value;}
148
148
  continue;
149
149
  }
150
150
  if (arg.startsWith("-")) {
@@ -153,23 +153,23 @@ function parseNpmExecArgs(args: string[]): ParsedInvocation | null {
153
153
  }
154
154
 
155
155
  const binName = after[0];
156
- if (!packageSpec || !binName) return null;
156
+ if (!packageSpec || !binName) {return null;}
157
157
  const extraArgs = after.slice(1);
158
158
  return { packageSpec, binName, extraArgs };
159
159
  }
160
160
 
161
161
  function resolveFromNpmCache(packageSpec: string, binName?: string): NpxCacheEntry | null {
162
162
  const cacheDir = getNpmCacheDir();
163
- if (!cacheDir) return null;
163
+ if (!cacheDir) {return null;}
164
164
 
165
165
  const packageName = extractPackageName(packageSpec);
166
- if (!packageName) return null;
166
+ if (!packageName) {return null;}
167
167
 
168
168
  const packageDir = findCachedPackageDir(cacheDir, packageName);
169
- if (!packageDir) return null;
169
+ if (!packageDir) {return null;}
170
170
 
171
171
  const packageJsonPath = join(packageDir, "package.json");
172
- if (!existsSync(packageJsonPath)) return null;
172
+ if (!existsSync(packageJsonPath)) {return null;}
173
173
 
174
174
  let pkg: { bin?: string | Record<string, string>; version?: string } | null = null;
175
175
  try {
@@ -182,7 +182,7 @@ function resolveFromNpmCache(packageSpec: string, binName?: string): NpxCacheEnt
182
182
  }
183
183
 
184
184
  const binField = pkg?.bin;
185
- if (!binField) return null;
185
+ if (!binField) {return null;}
186
186
 
187
187
  const candidates = buildBinCandidates(packageName, binName);
188
188
  let chosenBinName: string | undefined;
@@ -208,14 +208,14 @@ function resolveFromNpmCache(packageSpec: string, binName?: string): NpxCacheEnt
208
208
  }
209
209
  }
210
210
 
211
- if (!binRel) return null;
211
+ if (!binRel) {return null;}
212
212
 
213
213
  const nodeModulesDir = findNodeModulesDir(packageDir);
214
214
  const binLink = chosenBinName ? join(nodeModulesDir, ".bin", chosenBinName) : null;
215
215
  let resolvedBin = binLink && existsSync(binLink) ? safeRealpath(binLink) : "";
216
216
  if (!resolvedBin) {
217
217
  resolvedBin = resolve(packageDir, binRel);
218
- if (!existsSync(resolvedBin)) return null;
218
+ if (!existsSync(resolvedBin)) {return null;}
219
219
  }
220
220
 
221
221
  const isJs = detectJsBinary(resolvedBin);
@@ -252,13 +252,13 @@ async function forceNpxCache(packageSpec: string): Promise<void> {
252
252
 
253
253
  function buildBinCandidates(packageName: string, explicitBin?: string): string[] {
254
254
  const candidates: string[] = [];
255
- if (explicitBin) candidates.push(explicitBin);
255
+ if (explicitBin) {candidates.push(explicitBin);}
256
256
 
257
257
  if (packageName.startsWith("@")) {
258
258
  const namePart = packageName.split("/")[1] ?? "";
259
259
  const scopePart = packageName.split("/")[0]?.replace("@", "") ?? "";
260
- if (namePart) candidates.push(namePart);
261
- if (scopePart && namePart) candidates.push(`${scopePart}-${namePart}`);
260
+ if (namePart) {candidates.push(namePart);}
261
+ if (scopePart && namePart) {candidates.push(`${scopePart}-${namePart}`);}
262
262
  } else {
263
263
  candidates.push(packageName);
264
264
  }
@@ -268,10 +268,10 @@ function buildBinCandidates(packageName: string, explicitBin?: string): string[]
268
268
 
269
269
  function extractPackageName(spec: string): string | null {
270
270
  const trimmed = spec.trim();
271
- if (!trimmed) return null;
271
+ if (!trimmed) {return null;}
272
272
  if (trimmed.startsWith("@")) {
273
273
  const slashIndex = trimmed.indexOf("/");
274
- if (slashIndex < 0) return null;
274
+ if (slashIndex < 0) {return null;}
275
275
  const atIndex = trimmed.lastIndexOf("@");
276
276
  if (atIndex > slashIndex) {
277
277
  return trimmed.slice(0, atIndex);
@@ -292,7 +292,7 @@ function defaultBinName(packageName: string): string {
292
292
 
293
293
  function findCachedPackageDir(cacheDir: string, packageName: string): string | null {
294
294
  const npxDir = join(cacheDir, "_npx");
295
- if (!existsSync(npxDir)) return null;
295
+ if (!existsSync(npxDir)) {return null;}
296
296
 
297
297
  const packagePathParts = packageName.startsWith("@")
298
298
  ? packageName.split("/")
@@ -328,7 +328,7 @@ function findNodeModulesDir(packageDir: string): string {
328
328
 
329
329
  function detectJsBinary(binPath: string): boolean {
330
330
  const ext = extname(binPath).toLowerCase();
331
- if (ext === ".js" || ext === ".mjs" || ext === ".cjs") return true;
331
+ if (ext === ".js" || ext === ".mjs" || ext === ".cjs") {return true;}
332
332
  try {
333
333
  const fd = openSync(binPath, "r");
334
334
  try {
@@ -347,7 +347,7 @@ function detectJsBinary(binPath: string): boolean {
347
347
  let npmCacheDirCached: string | null | undefined;
348
348
 
349
349
  function getNpmCacheDir(): string | null {
350
- if (npmCacheDirCached !== undefined) return npmCacheDirCached;
350
+ if (npmCacheDirCached !== undefined) {return npmCacheDirCached;}
351
351
  if (process.env.NPM_CONFIG_CACHE) {
352
352
  npmCacheDirCached = process.env.NPM_CONFIG_CACHE;
353
353
  return npmCacheDirCached;
@@ -368,12 +368,12 @@ function getNpmCacheDir(): string | null {
368
368
  }
369
369
 
370
370
  function loadCache(): NpxCache | null {
371
- if (!existsSync(CACHE_PATH)) return null;
371
+ if (!existsSync(CACHE_PATH)) {return null;}
372
372
  try {
373
373
  const raw = JSON.parse(readFileSync(CACHE_PATH, "utf-8"));
374
- if (!raw || typeof raw !== "object") return null;
375
- if (raw.version !== CACHE_VERSION) return null;
376
- if (!raw.entries || typeof raw.entries !== "object") return null;
374
+ if (!raw || typeof raw !== "object") {return null;}
375
+ if (raw.version !== CACHE_VERSION) {return null;}
376
+ if (!raw.entries || typeof raw.entries !== "object") {return null;}
377
377
  return raw as NpxCache;
378
378
  } catch {
379
379
  return null;
@@ -26,7 +26,7 @@ function getTokensPath(serverName: string): string {
26
26
  export function getStoredTokens(serverName: string): OAuthTokens | undefined {
27
27
  const tokensPath = getTokensPath(serverName);
28
28
 
29
- if (!existsSync(tokensPath)) return undefined;
29
+ if (!existsSync(tokensPath)) {return undefined;}
30
30
 
31
31
  try {
32
32
  const stored = JSON.parse(readFileSync(tokensPath, "utf-8"));
@@ -217,7 +217,7 @@ export function executeSearch(
217
217
  if (!server && getPiTools) {
218
218
  const piTools = getPiTools();
219
219
  for (const tool of piTools) {
220
- if (tool.name === "mcp") continue;
220
+ if (tool.name === "mcp") {continue;}
221
221
 
222
222
  if (pattern.test(tool.name) || pattern.test(tool.description ?? "")) {
223
223
  piMatches.push({
@@ -229,7 +229,7 @@ export function executeSearch(
229
229
  }
230
230
 
231
231
  for (const [serverName, metadata] of state.toolMetadata.entries()) {
232
- if (server && serverName !== server) continue;
232
+ if (server && serverName !== server) {continue;}
233
233
  for (const tool of metadata) {
234
234
  if (pattern.test(tool.name) || pattern.test(tool.description)) {
235
235
  matches.push({
@@ -347,7 +347,7 @@ export function executeList(state: McpExtensionState, server: string): ProxyTool
347
347
  const desc = descMap.get(tool) ?? "";
348
348
  const truncated = truncateAtWord(desc, 50);
349
349
  text += `- ${tool}`;
350
- if (truncated) text += ` - ${truncated}`;
350
+ if (truncated) {text += ` - ${truncated}`;}
351
351
  text += "\n";
352
352
  }
353
353
 
@@ -444,10 +444,10 @@ export async function executeCall(
444
444
 
445
445
  for (const { name: configuredServer } of candidates) {
446
446
  const failedAgo = getFailureAgeSeconds(state, configuredServer);
447
- if (failedAgo !== null) continue;
447
+ if (failedAgo !== null) {continue;}
448
448
  const connected = await lazyConnect(state, configuredServer);
449
- if (!connected) continue;
450
- if (!prefixMatchedServer) prefixMatchedServer = configuredServer;
449
+ if (!connected) {continue;}
450
+ if (!prefixMatchedServer) {prefixMatchedServer = configuredServer;}
451
451
  toolMeta = findToolByName(state.toolMetadata.get(configuredServer), toolName);
452
452
  if (toolMeta) {
453
453
  serverName = configuredServer;
@@ -540,12 +540,12 @@ export async function executeCall(
540
540
 
541
541
  uiSession = toolMeta.uiResourceUri
542
542
  ? await maybeStartUiSession(state, {
543
- serverName,
544
- toolName: toolMeta.originalName,
545
- toolArgs: args ?? {},
546
- uiResourceUri: toolMeta.uiResourceUri,
547
- streamMode: toolMeta.uiStreamMode,
548
- })
543
+ serverName,
544
+ toolName: toolMeta.originalName,
545
+ toolArgs: args ?? {},
546
+ uiResourceUri: toolMeta.uiResourceUri,
547
+ streamMode: toolMeta.uiStreamMode,
548
+ })
549
549
  : null;
550
550
 
551
551
  const resultPromise = connection.client.callTool({
@@ -206,7 +206,7 @@ export class McpServerManager {
206
206
  private attachAdapterNotificationHandlers(serverName: string, client: Client): void {
207
207
  client.setNotificationHandler(serverStreamResultPatchNotificationSchema, (notification) => {
208
208
  const listener = this.uiStreamListeners.get(notification.params.streamToken);
209
- if (!listener) return;
209
+ if (!listener) {return;}
210
210
  listener(serverName, notification.params);
211
211
  });
212
212
  }
@@ -237,7 +237,7 @@ export class McpServerManager {
237
237
 
238
238
  async close(name: string): Promise<void> {
239
239
  const connection = this.connections.get(name);
240
- if (!connection) return;
240
+ if (!connection) {return;}
241
241
 
242
242
  // Delete from map BEFORE async cleanup to prevent a race where a
243
243
  // concurrent connect() creates a new connection that our deferred
@@ -284,8 +284,8 @@ export class McpServerManager {
284
284
 
285
285
  isIdle(name: string, timeoutMs: number): boolean {
286
286
  const connection = this.connections.get(name);
287
- if (!connection || connection.status !== "connected") return false;
288
- if (connection.inFlight > 0) return false;
287
+ if (!connection || connection.status !== "connected") {return false;}
288
+ if (connection.inFlight > 0) {return false;}
289
289
  return (Date.now() - connection.lastUsedAt) > timeoutMs;
290
290
  }
291
291
  }
@@ -302,7 +302,7 @@ function resolveEnv(env?: Record<string, string>): Record<string, string> {
302
302
  }
303
303
  }
304
304
 
305
- if (!env) return resolved;
305
+ if (!env) {return resolved;}
306
306
 
307
307
  for (const [key, value] of Object.entries(env)) {
308
308
  // Support ${VAR} and $env:VAR interpolation
@@ -318,7 +318,7 @@ function resolveEnv(env?: Record<string, string>): Record<string, string> {
318
318
  * Resolve headers with environment variable interpolation.
319
319
  */
320
320
  function resolveHeaders(headers?: Record<string, string>): Record<string, string> | undefined {
321
- if (!headers) return undefined;
321
+ if (!headers) {return undefined;}
322
322
 
323
323
  const resolved: Record<string, string> = {};
324
324
  for (const [key, value] of Object.entries(headers)) {
@@ -64,9 +64,9 @@ export function totalToolCount(state: McpExtensionState): number {
64
64
  }
65
65
 
66
66
  export function findToolByName(metadata: ToolMetadata[] | undefined, toolName: string): ToolMetadata | undefined {
67
- if (!metadata) return undefined;
67
+ if (!metadata) {return undefined;}
68
68
  const exact = metadata.find(m => m.name === toolName);
69
- if (exact) return exact;
69
+ if (exact) {return exact;}
70
70
  const normalized = toolName.replace(/-/g, "_");
71
71
  return metadata.find(m => m.name.replace(/-/g, "_") === normalized);
72
72
  }
@@ -129,8 +129,8 @@ function formatProperty(name: string, schema: unknown, required: boolean, indent
129
129
  }
130
130
 
131
131
  parts.push(`${indent}${name}`);
132
- if (typeStr) parts.push(`(${typeStr})`);
133
- if (required) parts.push("*required*");
132
+ if (typeStr) {parts.push(`(${typeStr})`);}
133
+ if (required) {parts.push("*required*");}
134
134
 
135
135
  if (s.description && typeof s.description === "string") {
136
136
  parts.push(`- ${s.description}`);
@@ -345,10 +345,10 @@ export function getServerPrefix(
345
345
  serverName: string,
346
346
  mode: "server" | "none" | "short"
347
347
  ): string {
348
- if (mode === "none") return "";
348
+ if (mode === "none") {return "";}
349
349
  if (mode === "short") {
350
350
  let short = serverName.replace(/-?mcp$/i, "").replace(/-/g, "_");
351
- if (!short) short = "mcp";
351
+ if (!short) {short = "mcp";}
352
352
  return short;
353
353
  }
354
354
  return serverName.replace(/-/g, "_");
@@ -80,9 +80,9 @@ export class UiResourceHandler {
80
80
 
81
81
  private getListResourceMeta(serverName: string, uri: string): Record<string, unknown> | undefined {
82
82
  const connection = this.manager.getConnection(serverName);
83
- if (!connection?.resources?.length) return undefined;
83
+ if (!connection?.resources?.length) {return undefined;}
84
84
  const resource = connection.resources.find((entry) => entry.uri === uri);
85
- if (!resource || !resource._meta || typeof resource._meta !== "object") return undefined;
85
+ if (!resource || !resource._meta || typeof resource._meta !== "object") {return undefined;}
86
86
  return resource._meta;
87
87
  }
88
88
  }
@@ -94,12 +94,12 @@ function selectContent(result: ReadResourceResult, preferredUri: string): Resour
94
94
  }
95
95
 
96
96
  const byUri = contents.find((content) => content.uri === preferredUri);
97
- if (byUri) return byUri;
97
+ if (byUri) {return byUri;}
98
98
 
99
99
  const byHtmlMime = contents.find(
100
100
  (content) => content.mimeType && isHtmlMimeType(content.mimeType)
101
101
  );
102
- if (byHtmlMime) return byHtmlMime;
102
+ if (byHtmlMime) {return byHtmlMime;}
103
103
 
104
104
  return contents[0];
105
105
  }
@@ -122,9 +122,9 @@ function toHtml(content: ResourceContentRecord): string {
122
122
  }
123
123
 
124
124
  function extractUiMeta(meta: Record<string, unknown> | undefined): UiResourceMeta {
125
- if (!meta || typeof meta !== "object") return {};
125
+ if (!meta || typeof meta !== "object") {return {};}
126
126
  const ui = meta.ui as Record<string, unknown> | undefined;
127
- if (!ui || typeof ui !== "object") return {};
127
+ if (!ui || typeof ui !== "object") {return {};}
128
128
 
129
129
  const out: UiResourceMeta = {};
130
130
 
@@ -123,7 +123,7 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
123
123
 
124
124
  const updateStreamSummary = (payload: unknown) => {
125
125
  const envelope = getVisualizationStreamEnvelope((payload as { structuredContent?: unknown } | null)?.structuredContent);
126
- if (!envelope) return;
126
+ if (!envelope) {return;}
127
127
  if (!streamSummary) {
128
128
  streamSummary = {
129
129
  streamId: envelope.streamId,
@@ -156,7 +156,7 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
156
156
  };
157
157
 
158
158
  const pruneEventLog = () => {
159
- if (eventLog.length <= MAX_EVENT_LOG) return;
159
+ if (eventLog.length <= MAX_EVENT_LOG) {return;}
160
160
  const latestCheckpointIndex = getLatestCheckpointIndex();
161
161
 
162
162
  if (latestCheckpointIndex > 0) {
@@ -169,7 +169,7 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
169
169
  };
170
170
 
171
171
  const pushEvent = (name: string, payload: unknown) => {
172
- if (completed) return;
172
+ if (completed) {return;}
173
173
  const eventId = nextEventId++;
174
174
  eventLog.push({ id: eventId, name, payload });
175
175
  updateStreamSummary(payload);
@@ -189,9 +189,9 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
189
189
  const eventsToReplay = Number.isFinite(parsedLastId)
190
190
  ? eventLog.filter((entry) => entry.id > parsedLastId)
191
191
  : (() => {
192
- const latestCheckpointIndex = getLatestCheckpointIndex();
193
- return latestCheckpointIndex >= 0 ? eventLog.slice(latestCheckpointIndex) : eventLog;
194
- })();
192
+ const latestCheckpointIndex = getLatestCheckpointIndex();
193
+ return latestCheckpointIndex >= 0 ? eventLog.slice(latestCheckpointIndex) : eventLog;
194
+ })();
195
195
 
196
196
  for (const entry of eventsToReplay) {
197
197
  try {
@@ -213,13 +213,13 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
213
213
  };
214
214
 
215
215
  const stopWatchdog = () => {
216
- if (!watchdog) return;
216
+ if (!watchdog) {return;}
217
217
  clearInterval(watchdog);
218
218
  watchdog = null;
219
219
  };
220
220
 
221
221
  const markCompleted = (reason: string) => {
222
- if (completed) return;
222
+ if (completed) {return;}
223
223
  log.debug("Session completed", { reason });
224
224
  pushEvent("session-complete", { reason });
225
225
  completed = true;
@@ -227,13 +227,13 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
227
227
  options.onComplete?.(reason);
228
228
  };
229
229
 
230
- const server = http.createServer(async (req, res) => {
230
+ const server = http.createServer(async(req, res) => {
231
231
  try {
232
232
  const method = req.method || "GET";
233
233
  const url = new URL(req.url || "/", `http://${req.headers.host || "127.0.0.1"}`);
234
234
 
235
235
  if (method === "GET" && url.pathname === "/") {
236
- if (!validateTokenQuery(url, sessionToken, res)) return;
236
+ if (!validateTokenQuery(url, sessionToken, res)) {return;}
237
237
  touchHeartbeat();
238
238
 
239
239
  const html = buildHostHtmlTemplate({
@@ -257,7 +257,7 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
257
257
  }
258
258
 
259
259
  if (method === "GET" && url.pathname === "/events") {
260
- if (!validateTokenQuery(url, sessionToken, res)) return;
260
+ if (!validateTokenQuery(url, sessionToken, res)) {return;}
261
261
  touchHeartbeat();
262
262
  log.debug("SSE client connected", { clientCount: sseClients.size + 1 });
263
263
  res.writeHead(200, {
@@ -276,13 +276,13 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
276
276
  }
277
277
 
278
278
  if (method === "GET" && url.pathname === "/health") {
279
- if (!validateTokenQuery(url, sessionToken, res)) return;
279
+ if (!validateTokenQuery(url, sessionToken, res)) {return;}
280
280
  sendJson(res, 200, { ok: true, result: { healthy: true } });
281
281
  return;
282
282
  }
283
283
 
284
284
  if (method === "GET" && url.pathname === "/ui-app") {
285
- if (!validateTokenQuery(url, sessionToken, res)) return;
285
+ if (!validateTokenQuery(url, sessionToken, res)) {return;}
286
286
  touchHeartbeat();
287
287
  // Serve the MCP app's UI HTML directly (avoids blob URL security issues)
288
288
  // Apply CSP meta tag if specified in resource metadata
@@ -318,8 +318,8 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
318
318
  }
319
319
 
320
320
  const body = await parseBody(req, res);
321
- if (!body) return;
322
- if (!validateTokenBody(body, sessionToken, res)) return;
321
+ if (!body) {return;}
322
+ if (!validateTokenBody(body, sessionToken, res)) {return;}
323
323
  const params = body.params ?? {};
324
324
  touchHeartbeat();
325
325
 
@@ -478,8 +478,8 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
478
478
  }
479
479
 
480
480
  watchdog = setInterval(() => {
481
- if (completed) return;
482
- if (Date.now() - lastHeartbeatAt <= ABANDONED_GRACE_MS) return;
481
+ if (completed) {return;}
482
+ if (Date.now() - lastHeartbeatAt <= ABANDONED_GRACE_MS) {return;}
483
483
  markCompleted("stale");
484
484
  try {
485
485
  server.close();