viyv-daemon 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -213,192 +213,6 @@ var init_registry = __esm({
213
213
  }
214
214
  });
215
215
 
216
- // src/config/daemon-presets.ts
217
- function isValidDaemonType(type) {
218
- return Object.values(DaemonType).includes(type);
219
- }
220
- var DaemonType, DAEMON_TYPE_CHOICES;
221
- var init_daemon_presets = __esm({
222
- "src/config/daemon-presets.ts"() {
223
- "use strict";
224
- DaemonType = /* @__PURE__ */ ((DaemonType2) => {
225
- DaemonType2["DEVELOPMENT"] = "development";
226
- DaemonType2["PROJECT_MANAGEMENT"] = "pm";
227
- DaemonType2["CUSTOMER_SUPPORT"] = "cs";
228
- DaemonType2["QUALITY_ASSURANCE"] = "qa";
229
- DaemonType2["GENERAL"] = "general";
230
- return DaemonType2;
231
- })(DaemonType || {});
232
- DAEMON_TYPE_CHOICES = [
233
- {
234
- name: "\u958B\u767A\u5411\u3051 (Development) - \u30B3\u30FC\u30C9\u958B\u767A\u30FB\u30C7\u30D0\u30C3\u30B0\u30FB\u30C7\u30D7\u30ED\u30A4",
235
- value: "development" /* DEVELOPMENT */
236
- },
237
- {
238
- name: "PM\u5411\u3051 (Project Management) - \u30BF\u30B9\u30AF\u7BA1\u7406\u30FB\u9032\u6357\u5831\u544A\u30FB\u30EA\u30B9\u30AF\u7BA1\u7406",
239
- value: "pm" /* PROJECT_MANAGEMENT */
240
- },
241
- {
242
- name: "CS\u5411\u3051 (Customer Support) - \u9867\u5BA2\u5BFE\u5FDC\u30FB\u30CA\u30EC\u30C3\u30B8\u30D9\u30FC\u30B9\u7BA1\u7406",
243
- value: "cs" /* CUSTOMER_SUPPORT */
244
- },
245
- {
246
- name: "QA\u5411\u3051 (Quality Assurance) - \u30C6\u30B9\u30C8\u8A08\u753B\u30FB\u30D0\u30B0\u8FFD\u8DE1\u30FB\u54C1\u8CEA\u7BA1\u7406",
247
- value: "qa" /* QUALITY_ASSURANCE */
248
- },
249
- {
250
- name: "\u6C4E\u7528 (Business General) - \u30D3\u30B8\u30CD\u30B9\u5168\u822C\u306E\u696D\u52D9\u52B9\u7387\u5316",
251
- value: "general" /* GENERAL */
252
- }
253
- ];
254
- }
255
- });
256
-
257
- // src/config/daemon-configs.ts
258
- var daemon_configs_exports = {};
259
- __export(daemon_configs_exports, {
260
- createDaemonConfig: () => createDaemonConfig,
261
- deleteDaemonConfig: () => deleteDaemonConfig,
262
- getDaemonConfig: () => getDaemonConfig,
263
- getDaemonConfigsPath: () => getDaemonConfigsPath,
264
- listDaemonConfigs: () => listDaemonConfigs,
265
- loadDaemonConfigs: () => loadDaemonConfigs,
266
- saveDaemonConfigs: () => saveDaemonConfigs,
267
- updateDaemonConfig: () => updateDaemonConfig
268
- });
269
- import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "fs";
270
- import { dirname as dirname3 } from "path";
271
- import { randomUUID as randomUUID2 } from "crypto";
272
- function getDaemonConfigsPath() {
273
- return `${getConfigDir()}/daemon-configs.json`;
274
- }
275
- function loadDaemonConfigs() {
276
- const configsPath = getDaemonConfigsPath();
277
- if (!existsSync5(configsPath)) {
278
- return { daemons: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
279
- }
280
- try {
281
- const content = readFileSync4(configsPath, "utf-8");
282
- const configs = JSON.parse(content);
283
- let currentWorkspaceId;
284
- try {
285
- const state = loadConfig();
286
- currentWorkspaceId = state.config.workspaceId;
287
- } catch {
288
- }
289
- let needsSave = false;
290
- for (const daemon of configs.daemons) {
291
- if (!daemon.id) {
292
- daemon.id = randomUUID2();
293
- needsSave = true;
294
- }
295
- if (!daemon.type || !isValidDaemonType(daemon.type)) {
296
- daemon.type = "general" /* GENERAL */;
297
- needsSave = true;
298
- }
299
- if (!daemon.workspaceId && currentWorkspaceId) {
300
- daemon.workspaceId = currentWorkspaceId;
301
- needsSave = true;
302
- }
303
- if (!daemon.mode) {
304
- daemon.mode = "team";
305
- needsSave = true;
306
- }
307
- }
308
- if (needsSave) {
309
- saveDaemonConfigs(configs);
310
- }
311
- return configs;
312
- } catch {
313
- return { daemons: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
314
- }
315
- }
316
- function saveDaemonConfigs(configs) {
317
- const configsPath = getDaemonConfigsPath();
318
- const dir = dirname3(configsPath);
319
- if (!existsSync5(dir)) {
320
- mkdirSync4(dir, { recursive: true, mode: 448 });
321
- }
322
- configs.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
323
- writeFileSync4(configsPath, JSON.stringify(configs, null, 2), { mode: 384 });
324
- }
325
- function createDaemonConfig(name, workspaceId, description, type = "general" /* GENERAL */, mode = "agent", supervisorName) {
326
- const configs = loadDaemonConfigs();
327
- if (configs.daemons.some((d) => d.name === name && d.workspaceId === workspaceId)) {
328
- throw new Error(`Daemon '${name}' already exists in this workspace`);
329
- }
330
- const now = (/* @__PURE__ */ new Date()).toISOString();
331
- const entry = {
332
- id: randomUUID2(),
333
- name,
334
- description,
335
- type,
336
- mode,
337
- workspaceId,
338
- supervisorName,
339
- createdAt: now,
340
- updatedAt: now
341
- };
342
- configs.daemons.push(entry);
343
- saveDaemonConfigs(configs);
344
- return entry;
345
- }
346
- function deleteDaemonConfig(name, workspaceId) {
347
- const configs = loadDaemonConfigs();
348
- const index25 = workspaceId ? configs.daemons.findIndex((d) => d.name === name && d.workspaceId === workspaceId) : configs.daemons.findIndex((d) => d.name === name);
349
- if (index25 === -1) {
350
- return false;
351
- }
352
- configs.daemons.splice(index25, 1);
353
- saveDaemonConfigs(configs);
354
- return true;
355
- }
356
- function getDaemonConfig(name, workspaceId) {
357
- const configs = loadDaemonConfigs();
358
- if (workspaceId) {
359
- return configs.daemons.find((d) => d.name === name && d.workspaceId === workspaceId);
360
- }
361
- return configs.daemons.find((d) => d.name === name);
362
- }
363
- function listDaemonConfigs(workspaceId, supervisorName) {
364
- const configs = loadDaemonConfigs();
365
- let result = configs.daemons;
366
- if (workspaceId) {
367
- result = result.filter((d) => d.workspaceId === workspaceId);
368
- }
369
- if (supervisorName !== void 0) {
370
- result = result.filter((d) => (d.supervisorName || null) === supervisorName);
371
- }
372
- return result;
373
- }
374
- function updateDaemonConfig(name, updates, workspaceId) {
375
- const configs = loadDaemonConfigs();
376
- const daemon = workspaceId ? configs.daemons.find((d) => d.name === name && d.workspaceId === workspaceId) : configs.daemons.find((d) => d.name === name);
377
- if (!daemon) {
378
- return void 0;
379
- }
380
- if (updates.description !== void 0) {
381
- daemon.description = updates.description;
382
- }
383
- if (updates.mode !== void 0) {
384
- daemon.mode = updates.mode;
385
- }
386
- if (updates.chromeProfilePath !== void 0) {
387
- daemon.chromeProfilePath = updates.chromeProfilePath || void 0;
388
- }
389
- daemon.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
390
- saveDaemonConfigs(configs);
391
- return daemon;
392
- }
393
- var init_daemon_configs = __esm({
394
- "src/config/daemon-configs.ts"() {
395
- "use strict";
396
- init_types();
397
- init_daemon_presets();
398
- init_loader();
399
- }
400
- });
401
-
402
216
  // ../../packages/shared/dist/types/agent.js
403
217
  var DEFAULT_MODEL_SETTINGS;
404
218
  var init_agent = __esm({
@@ -1835,7 +1649,7 @@ var init_security2 = __esm({
1835
1649
  // ../../packages/core/dist/plugin/local-plugin-cache.js
1836
1650
  import { createHash } from "crypto";
1837
1651
  import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2, rm, access } from "fs/promises";
1838
- import { join as join8 } from "path";
1652
+ import { join as join7 } from "path";
1839
1653
  var init_local_plugin_cache = __esm({
1840
1654
  "../../packages/core/dist/plugin/local-plugin-cache.js"() {
1841
1655
  "use strict";
@@ -1851,8 +1665,8 @@ var init_plugin_sync_manager = __esm({
1851
1665
  });
1852
1666
 
1853
1667
  // ../../packages/core/dist/plugin/plugin-manager.js
1854
- import { homedir as homedir6 } from "os";
1855
- import { join as join9 } from "path";
1668
+ import { homedir as homedir5 } from "os";
1669
+ import { join as join8 } from "path";
1856
1670
  var init_plugin_manager = __esm({
1857
1671
  "../../packages/core/dist/plugin/plugin-manager.js"() {
1858
1672
  "use strict";
@@ -2040,15 +1854,15 @@ var agent_info_scanner_exports = {};
2040
1854
  __export(agent_info_scanner_exports, {
2041
1855
  scanAgentInfo: () => scanAgentInfo
2042
1856
  });
2043
- import { existsSync as existsSync11, readdirSync as readdirSync3, readFileSync as readFileSync10 } from "fs";
2044
- import { join as join10 } from "path";
1857
+ import { existsSync as existsSync9, readdirSync as readdirSync2, readFileSync as readFileSync8 } from "fs";
1858
+ import { join as join9 } from "path";
2045
1859
  async function scanMcpServers(cwd) {
2046
- const mcpJsonPath = join10(cwd, ".mcp.json");
2047
- if (!existsSync11(mcpJsonPath)) {
1860
+ const mcpJsonPath = join9(cwd, ".mcp.json");
1861
+ if (!existsSync9(mcpJsonPath)) {
2048
1862
  return [];
2049
1863
  }
2050
1864
  try {
2051
- const content = readFileSync10(mcpJsonPath, "utf-8");
1865
+ const content = readFileSync8(mcpJsonPath, "utf-8");
2052
1866
  const config = JSON.parse(content);
2053
1867
  if (!config.mcpServers || Object.keys(config.mcpServers).length === 0) {
2054
1868
  return [];
@@ -2111,19 +1925,19 @@ function extractSkillMetadata(content) {
2111
1925
  return result;
2112
1926
  }
2113
1927
  function scanSkills(cwd) {
2114
- const skillsDir = join10(cwd, ".claude", "skills");
2115
- if (!existsSync11(skillsDir)) {
1928
+ const skillsDir = join9(cwd, ".claude", "skills");
1929
+ if (!existsSync9(skillsDir)) {
2116
1930
  return [];
2117
1931
  }
2118
1932
  const skills = [];
2119
1933
  try {
2120
- const entries = readdirSync3(skillsDir, { withFileTypes: true });
1934
+ const entries = readdirSync2(skillsDir, { withFileTypes: true });
2121
1935
  for (const entry of entries) {
2122
1936
  if (!entry.isDirectory()) continue;
2123
- const skillMdPath = join10(skillsDir, entry.name, "SKILL.md");
2124
- if (!existsSync11(skillMdPath)) continue;
1937
+ const skillMdPath = join9(skillsDir, entry.name, "SKILL.md");
1938
+ if (!existsSync9(skillMdPath)) continue;
2125
1939
  try {
2126
- const content = readFileSync10(skillMdPath, "utf-8");
1940
+ const content = readFileSync8(skillMdPath, "utf-8");
2127
1941
  const metadata = extractSkillMetadata(content);
2128
1942
  skills.push({
2129
1943
  name: entry.name,
@@ -2166,9 +1980,9 @@ function extractCommandMetadata(content) {
2166
1980
  }
2167
1981
  function scanCommandsDirRecursive(dir, prefix, commands, baseDir) {
2168
1982
  try {
2169
- const entries = readdirSync3(dir, { withFileTypes: true });
1983
+ const entries = readdirSync2(dir, { withFileTypes: true });
2170
1984
  for (const entry of entries) {
2171
- const fullPath = join10(dir, entry.name);
1985
+ const fullPath = join9(dir, entry.name);
2172
1986
  if (entry.isDirectory()) {
2173
1987
  const newPrefix = `${prefix}:${entry.name}`;
2174
1988
  scanCommandsDirRecursive(fullPath, newPrefix, commands, baseDir);
@@ -2177,7 +1991,7 @@ function scanCommandsDirRecursive(dir, prefix, commands, baseDir) {
2177
1991
  const id = `${prefix}:${baseName}`;
2178
1992
  const filePath = fullPath.replace(baseDir, ".claude/commands").replace(/^\//, "");
2179
1993
  try {
2180
- const content = readFileSync10(fullPath, "utf-8");
1994
+ const content = readFileSync8(fullPath, "utf-8");
2181
1995
  const metadata = extractCommandMetadata(content);
2182
1996
  commands.push({
2183
1997
  id,
@@ -2194,15 +2008,15 @@ function scanCommandsDirRecursive(dir, prefix, commands, baseDir) {
2194
2008
  }
2195
2009
  }
2196
2010
  function scanCommands(cwd) {
2197
- const commandsDir = join10(cwd, ".claude", "commands");
2011
+ const commandsDir = join9(cwd, ".claude", "commands");
2198
2012
  const commands = [];
2199
- if (!existsSync11(commandsDir)) {
2013
+ if (!existsSync9(commandsDir)) {
2200
2014
  return commands;
2201
2015
  }
2202
2016
  const categories = ["user", "sys", "tpl"];
2203
2017
  for (const category of categories) {
2204
- const categoryDir = join10(commandsDir, category);
2205
- if (existsSync11(categoryDir)) {
2018
+ const categoryDir = join9(commandsDir, category);
2019
+ if (existsSync9(categoryDir)) {
2206
2020
  scanCommandsDirRecursive(categoryDir, category, commands, commandsDir);
2207
2021
  }
2208
2022
  }
@@ -6538,22 +6352,22 @@ var init_command_presets = __esm({
6538
6352
  });
6539
6353
 
6540
6354
  // src/mcp/command-templates/utils.ts
6541
- import { existsSync as existsSync16, mkdirSync as mkdirSync14, writeFileSync as writeFileSync13 } from "fs";
6542
- import { join as join16 } from "path";
6355
+ import { existsSync as existsSync14, mkdirSync as mkdirSync12, writeFileSync as writeFileSync12 } from "fs";
6356
+ import { join as join15 } from "path";
6543
6357
  async function writeCommandFiles(commandsDir, commands) {
6544
- if (!existsSync16(commandsDir)) {
6545
- mkdirSync14(commandsDir, { recursive: true });
6358
+ if (!existsSync14(commandsDir)) {
6359
+ mkdirSync12(commandsDir, { recursive: true });
6546
6360
  }
6547
6361
  for (const [name, definition] of Object.entries(commands)) {
6548
- const targetDir = definition.namespace ? join16(commandsDir, definition.namespace) : commandsDir;
6549
- if (definition.namespace && !existsSync16(targetDir)) {
6550
- mkdirSync14(targetDir, { recursive: true });
6362
+ const targetDir = definition.namespace ? join15(commandsDir, definition.namespace) : commandsDir;
6363
+ if (definition.namespace && !existsSync14(targetDir)) {
6364
+ mkdirSync12(targetDir, { recursive: true });
6551
6365
  }
6552
- const filePath = join16(targetDir, `${name}.md`);
6553
- writeFileSync13(filePath, definition.content, "utf-8");
6366
+ const filePath = join15(targetDir, `${name}.md`);
6367
+ writeFileSync12(filePath, definition.content, "utf-8");
6554
6368
  if (definition.metadata) {
6555
- const metaPath = join16(targetDir, `${name}.meta.json`);
6556
- writeFileSync13(metaPath, JSON.stringify(definition.metadata, null, 2), "utf-8");
6369
+ const metaPath = join15(targetDir, `${name}.meta.json`);
6370
+ writeFileSync12(metaPath, JSON.stringify(definition.metadata, null, 2), "utf-8");
6557
6371
  }
6558
6372
  }
6559
6373
  }
@@ -12895,8 +12709,413 @@ var init_command_templates = __esm({
12895
12709
  }
12896
12710
  });
12897
12711
 
12712
+ // src/mcp/browser-mcp-process.ts
12713
+ import { spawn as spawn2 } from "child_process";
12714
+ import { existsSync as existsSync17, readFileSync as readFileSync14, unlinkSync as unlinkSync7, writeFileSync as writeFileSync15 } from "fs";
12715
+ import { tmpdir } from "os";
12716
+ import { join as join19 } from "path";
12717
+ async function isPortAlive(port) {
12718
+ try {
12719
+ const controller = new AbortController();
12720
+ const timeout = setTimeout(() => controller.abort(), 2e3);
12721
+ const res = await fetch(`http://127.0.0.1:${port}/sse`, {
12722
+ method: "GET",
12723
+ signal: controller.signal
12724
+ });
12725
+ clearTimeout(timeout);
12726
+ return res.status === 200;
12727
+ } catch {
12728
+ return false;
12729
+ }
12730
+ }
12731
+ function readPortFile() {
12732
+ try {
12733
+ if (!existsSync17(PORT_FILE)) return null;
12734
+ const content = readFileSync14(PORT_FILE, "utf-8").trim();
12735
+ const port = Number.parseInt(content, 10);
12736
+ if (Number.isNaN(port) || port <= 0 || port > 65535) return null;
12737
+ return port;
12738
+ } catch {
12739
+ return null;
12740
+ }
12741
+ }
12742
+ var PORT_FILE, BrowserMcpProcess;
12743
+ var init_browser_mcp_process = __esm({
12744
+ "src/mcp/browser-mcp-process.ts"() {
12745
+ "use strict";
12746
+ PORT_FILE = join19(tmpdir(), "viyv-browser-mcp.port");
12747
+ BrowserMcpProcess = class {
12748
+ process = null;
12749
+ port = null;
12750
+ /** Whether this instance owns (spawned) the process */
12751
+ isOwner = false;
12752
+ /**
12753
+ * Start the viyv-browser-mcp process in SSE mode.
12754
+ * If another instance is already running (detected via port file),
12755
+ * reuses that instance instead of spawning a new one.
12756
+ * @returns The port number the SSE server is listening on
12757
+ */
12758
+ async start() {
12759
+ if (this.port) {
12760
+ console.log("[BrowserMcpProcess] Already running on port", this.port);
12761
+ return this.port;
12762
+ }
12763
+ const existingPort = readPortFile();
12764
+ if (existingPort) {
12765
+ const alive = await isPortAlive(existingPort);
12766
+ if (alive) {
12767
+ console.log(
12768
+ `[BrowserMcpProcess] Reusing existing instance on port ${existingPort} (from ${PORT_FILE})`
12769
+ );
12770
+ this.port = existingPort;
12771
+ this.isOwner = false;
12772
+ return existingPort;
12773
+ }
12774
+ console.log(`[BrowserMcpProcess] Stale port file (port ${existingPort} not alive), removing`);
12775
+ try {
12776
+ unlinkSync7(PORT_FILE);
12777
+ } catch {
12778
+ }
12779
+ }
12780
+ return this.spawnProcess();
12781
+ }
12782
+ /**
12783
+ * Actually spawn the child process and write the port file.
12784
+ */
12785
+ spawnProcess() {
12786
+ return new Promise((resolve6, reject) => {
12787
+ const proc = spawn2("npx", ["viyv-browser-mcp", "--transport", "sse", "--port", "0"], {
12788
+ stdio: ["pipe", "pipe", "pipe"]
12789
+ });
12790
+ let stdoutBuf = "";
12791
+ let resolved = false;
12792
+ const timeout = setTimeout(() => {
12793
+ if (!resolved) {
12794
+ resolved = true;
12795
+ proc.kill();
12796
+ reject(new Error("[BrowserMcpProcess] Timed out waiting for port"));
12797
+ }
12798
+ }, 3e4);
12799
+ proc.stdout?.on("data", (chunk) => {
12800
+ if (resolved) return;
12801
+ stdoutBuf += chunk.toString();
12802
+ const nl = stdoutBuf.indexOf("\n");
12803
+ if (nl >= 0) {
12804
+ try {
12805
+ const { port } = JSON.parse(stdoutBuf.slice(0, nl));
12806
+ clearTimeout(timeout);
12807
+ resolved = true;
12808
+ this.process = proc;
12809
+ this.port = port;
12810
+ this.isOwner = true;
12811
+ try {
12812
+ writeFileSync15(PORT_FILE, String(port), "utf-8");
12813
+ console.log(`[BrowserMcpProcess] Wrote port file: ${PORT_FILE}`);
12814
+ } catch (err) {
12815
+ console.error("[BrowserMcpProcess] Failed to write port file:", err);
12816
+ }
12817
+ console.log(`[BrowserMcpProcess] Started on port ${port}`);
12818
+ resolve6(port);
12819
+ } catch (err) {
12820
+ clearTimeout(timeout);
12821
+ resolved = true;
12822
+ proc.kill();
12823
+ reject(
12824
+ new Error(
12825
+ `[BrowserMcpProcess] Failed to parse port from stdout: ${stdoutBuf.slice(0, nl)}`
12826
+ )
12827
+ );
12828
+ }
12829
+ }
12830
+ });
12831
+ proc.stderr?.on("data", (chunk) => {
12832
+ const line = chunk.toString().trim();
12833
+ if (line) {
12834
+ console.log(`[BrowserMcpProcess] ${line}`);
12835
+ }
12836
+ });
12837
+ proc.on("error", (err) => {
12838
+ if (!resolved) {
12839
+ clearTimeout(timeout);
12840
+ resolved = true;
12841
+ reject(new Error(`[BrowserMcpProcess] Failed to spawn: ${err.message}`));
12842
+ }
12843
+ });
12844
+ proc.on("exit", (code, signal) => {
12845
+ console.log(`[BrowserMcpProcess] Exited (code=${code}, signal=${signal})`);
12846
+ this.process = null;
12847
+ this.port = null;
12848
+ if (this.isOwner) {
12849
+ this.removePortFile();
12850
+ this.isOwner = false;
12851
+ }
12852
+ if (!resolved) {
12853
+ clearTimeout(timeout);
12854
+ resolved = true;
12855
+ reject(new Error(`[BrowserMcpProcess] Exited before reporting port (code=${code})`));
12856
+ }
12857
+ });
12858
+ });
12859
+ }
12860
+ /**
12861
+ * Stop the viyv-browser-mcp process.
12862
+ * Only kills the process if this instance owns it (spawned it).
12863
+ * Non-owner instances just clear their local state.
12864
+ */
12865
+ async stop() {
12866
+ if (!this.isOwner) {
12867
+ this.port = null;
12868
+ return;
12869
+ }
12870
+ const proc = this.process;
12871
+ if (!proc) {
12872
+ this.removePortFile();
12873
+ this.port = null;
12874
+ this.isOwner = false;
12875
+ return;
12876
+ }
12877
+ return new Promise((resolve6) => {
12878
+ const timeout = setTimeout(() => {
12879
+ proc.kill("SIGKILL");
12880
+ resolve6();
12881
+ }, 5e3);
12882
+ proc.on("exit", () => {
12883
+ clearTimeout(timeout);
12884
+ resolve6();
12885
+ });
12886
+ proc.kill("SIGTERM");
12887
+ this.process = null;
12888
+ this.port = null;
12889
+ this.removePortFile();
12890
+ this.isOwner = false;
12891
+ });
12892
+ }
12893
+ /**
12894
+ * Remove the port file if it exists.
12895
+ */
12896
+ removePortFile() {
12897
+ try {
12898
+ if (existsSync17(PORT_FILE)) {
12899
+ unlinkSync7(PORT_FILE);
12900
+ console.log(`[BrowserMcpProcess] Removed port file: ${PORT_FILE}`);
12901
+ }
12902
+ } catch {
12903
+ }
12904
+ }
12905
+ /**
12906
+ * Get the SSE URL for agents to connect to.
12907
+ */
12908
+ getUrl() {
12909
+ if (!this.port) return null;
12910
+ return `http://127.0.0.1:${this.port}`;
12911
+ }
12912
+ /**
12913
+ * Check if the process is running (or reusing an existing instance).
12914
+ */
12915
+ isRunning() {
12916
+ return this.port !== null;
12917
+ }
12918
+ /**
12919
+ * Get the port number.
12920
+ */
12921
+ getPort() {
12922
+ return this.port;
12923
+ }
12924
+ /**
12925
+ * Whether this instance spawned the process (vs reusing an existing one).
12926
+ */
12927
+ isProcessOwner() {
12928
+ return this.isOwner;
12929
+ }
12930
+ };
12931
+ }
12932
+ });
12933
+
12934
+ // src/config/daemon-presets.ts
12935
+ function isValidDaemonType(type) {
12936
+ return Object.values(DaemonType).includes(type);
12937
+ }
12938
+ var DaemonType, DAEMON_TYPE_CHOICES;
12939
+ var init_daemon_presets = __esm({
12940
+ "src/config/daemon-presets.ts"() {
12941
+ "use strict";
12942
+ DaemonType = /* @__PURE__ */ ((DaemonType2) => {
12943
+ DaemonType2["DEVELOPMENT"] = "development";
12944
+ DaemonType2["PROJECT_MANAGEMENT"] = "pm";
12945
+ DaemonType2["CUSTOMER_SUPPORT"] = "cs";
12946
+ DaemonType2["QUALITY_ASSURANCE"] = "qa";
12947
+ DaemonType2["GENERAL"] = "general";
12948
+ return DaemonType2;
12949
+ })(DaemonType || {});
12950
+ DAEMON_TYPE_CHOICES = [
12951
+ {
12952
+ name: "\u958B\u767A\u5411\u3051 (Development) - \u30B3\u30FC\u30C9\u958B\u767A\u30FB\u30C7\u30D0\u30C3\u30B0\u30FB\u30C7\u30D7\u30ED\u30A4",
12953
+ value: "development" /* DEVELOPMENT */
12954
+ },
12955
+ {
12956
+ name: "PM\u5411\u3051 (Project Management) - \u30BF\u30B9\u30AF\u7BA1\u7406\u30FB\u9032\u6357\u5831\u544A\u30FB\u30EA\u30B9\u30AF\u7BA1\u7406",
12957
+ value: "pm" /* PROJECT_MANAGEMENT */
12958
+ },
12959
+ {
12960
+ name: "CS\u5411\u3051 (Customer Support) - \u9867\u5BA2\u5BFE\u5FDC\u30FB\u30CA\u30EC\u30C3\u30B8\u30D9\u30FC\u30B9\u7BA1\u7406",
12961
+ value: "cs" /* CUSTOMER_SUPPORT */
12962
+ },
12963
+ {
12964
+ name: "QA\u5411\u3051 (Quality Assurance) - \u30C6\u30B9\u30C8\u8A08\u753B\u30FB\u30D0\u30B0\u8FFD\u8DE1\u30FB\u54C1\u8CEA\u7BA1\u7406",
12965
+ value: "qa" /* QUALITY_ASSURANCE */
12966
+ },
12967
+ {
12968
+ name: "\u6C4E\u7528 (Business General) - \u30D3\u30B8\u30CD\u30B9\u5168\u822C\u306E\u696D\u52D9\u52B9\u7387\u5316",
12969
+ value: "general" /* GENERAL */
12970
+ }
12971
+ ];
12972
+ }
12973
+ });
12974
+
12975
+ // src/config/daemon-configs.ts
12976
+ var daemon_configs_exports = {};
12977
+ __export(daemon_configs_exports, {
12978
+ createDaemonConfig: () => createDaemonConfig,
12979
+ deleteDaemonConfig: () => deleteDaemonConfig,
12980
+ getDaemonConfig: () => getDaemonConfig,
12981
+ getDaemonConfigsPath: () => getDaemonConfigsPath,
12982
+ listDaemonConfigs: () => listDaemonConfigs,
12983
+ loadDaemonConfigs: () => loadDaemonConfigs,
12984
+ saveDaemonConfigs: () => saveDaemonConfigs,
12985
+ updateDaemonConfig: () => updateDaemonConfig
12986
+ });
12987
+ import { existsSync as existsSync19, readFileSync as readFileSync16, writeFileSync as writeFileSync16, mkdirSync as mkdirSync15 } from "fs";
12988
+ import { dirname as dirname7 } from "path";
12989
+ import { randomUUID as randomUUID9 } from "crypto";
12990
+ function getDaemonConfigsPath() {
12991
+ return `${getConfigDir()}/daemon-configs.json`;
12992
+ }
12993
+ function loadDaemonConfigs() {
12994
+ const configsPath = getDaemonConfigsPath();
12995
+ if (!existsSync19(configsPath)) {
12996
+ return { daemons: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
12997
+ }
12998
+ try {
12999
+ const content = readFileSync16(configsPath, "utf-8");
13000
+ const configs = JSON.parse(content);
13001
+ let currentWorkspaceId;
13002
+ try {
13003
+ const state = loadConfig();
13004
+ currentWorkspaceId = state.config.workspaceId;
13005
+ } catch {
13006
+ }
13007
+ let needsSave = false;
13008
+ for (const daemon of configs.daemons) {
13009
+ if (!daemon.id) {
13010
+ daemon.id = randomUUID9();
13011
+ needsSave = true;
13012
+ }
13013
+ if (!daemon.type || !isValidDaemonType(daemon.type)) {
13014
+ daemon.type = "general" /* GENERAL */;
13015
+ needsSave = true;
13016
+ }
13017
+ if (!daemon.workspaceId && currentWorkspaceId) {
13018
+ daemon.workspaceId = currentWorkspaceId;
13019
+ needsSave = true;
13020
+ }
13021
+ if (!daemon.mode) {
13022
+ daemon.mode = "team";
13023
+ needsSave = true;
13024
+ }
13025
+ }
13026
+ if (needsSave) {
13027
+ saveDaemonConfigs(configs);
13028
+ }
13029
+ return configs;
13030
+ } catch {
13031
+ return { daemons: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
13032
+ }
13033
+ }
13034
+ function saveDaemonConfigs(configs) {
13035
+ const configsPath = getDaemonConfigsPath();
13036
+ const dir = dirname7(configsPath);
13037
+ if (!existsSync19(dir)) {
13038
+ mkdirSync15(dir, { recursive: true, mode: 448 });
13039
+ }
13040
+ configs.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
13041
+ writeFileSync16(configsPath, JSON.stringify(configs, null, 2), { mode: 384 });
13042
+ }
13043
+ function createDaemonConfig(name, workspaceId, description, type = "general" /* GENERAL */, mode = "agent", supervisorName) {
13044
+ const configs = loadDaemonConfigs();
13045
+ if (configs.daemons.some((d) => d.name === name && d.workspaceId === workspaceId)) {
13046
+ throw new Error(`Daemon '${name}' already exists in this workspace`);
13047
+ }
13048
+ const now = (/* @__PURE__ */ new Date()).toISOString();
13049
+ const entry = {
13050
+ id: randomUUID9(),
13051
+ name,
13052
+ description,
13053
+ type,
13054
+ mode,
13055
+ workspaceId,
13056
+ supervisorName,
13057
+ createdAt: now,
13058
+ updatedAt: now
13059
+ };
13060
+ configs.daemons.push(entry);
13061
+ saveDaemonConfigs(configs);
13062
+ return entry;
13063
+ }
13064
+ function deleteDaemonConfig(name, workspaceId) {
13065
+ const configs = loadDaemonConfigs();
13066
+ const index25 = workspaceId ? configs.daemons.findIndex((d) => d.name === name && d.workspaceId === workspaceId) : configs.daemons.findIndex((d) => d.name === name);
13067
+ if (index25 === -1) {
13068
+ return false;
13069
+ }
13070
+ configs.daemons.splice(index25, 1);
13071
+ saveDaemonConfigs(configs);
13072
+ return true;
13073
+ }
13074
+ function getDaemonConfig(name, workspaceId) {
13075
+ const configs = loadDaemonConfigs();
13076
+ if (workspaceId) {
13077
+ return configs.daemons.find((d) => d.name === name && d.workspaceId === workspaceId);
13078
+ }
13079
+ return configs.daemons.find((d) => d.name === name);
13080
+ }
13081
+ function listDaemonConfigs(workspaceId, supervisorName) {
13082
+ const configs = loadDaemonConfigs();
13083
+ let result = configs.daemons;
13084
+ if (workspaceId) {
13085
+ result = result.filter((d) => d.workspaceId === workspaceId);
13086
+ }
13087
+ if (supervisorName !== void 0) {
13088
+ result = result.filter((d) => (d.supervisorName || null) === supervisorName);
13089
+ }
13090
+ return result;
13091
+ }
13092
+ function updateDaemonConfig(name, updates, workspaceId) {
13093
+ const configs = loadDaemonConfigs();
13094
+ const daemon = workspaceId ? configs.daemons.find((d) => d.name === name && d.workspaceId === workspaceId) : configs.daemons.find((d) => d.name === name);
13095
+ if (!daemon) {
13096
+ return void 0;
13097
+ }
13098
+ if (updates.description !== void 0) {
13099
+ daemon.description = updates.description;
13100
+ }
13101
+ if (updates.mode !== void 0) {
13102
+ daemon.mode = updates.mode;
13103
+ }
13104
+ daemon.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
13105
+ saveDaemonConfigs(configs);
13106
+ return daemon;
13107
+ }
13108
+ var init_daemon_configs = __esm({
13109
+ "src/config/daemon-configs.ts"() {
13110
+ "use strict";
13111
+ init_types();
13112
+ init_daemon_presets();
13113
+ init_loader();
13114
+ }
13115
+ });
13116
+
12898
13117
  // src/supervisor/child-manager.ts
12899
- import { spawn as spawn3 } from "child_process";
13118
+ import { spawn as spawn4 } from "child_process";
12900
13119
  import { dirname as dirname12, join as join38 } from "path";
12901
13120
  import { fileURLToPath as fileURLToPath3 } from "url";
12902
13121
  import { EventEmitter as EventEmitter32 } from "events";
@@ -12915,11 +13134,18 @@ var init_child_manager = __esm({
12915
13134
  shuttingDown = false;
12916
13135
  supervisorInstanceId;
12917
13136
  workspaceId;
13137
+ browserMcpUrl = null;
12918
13138
  constructor(supervisorInstanceId, workspaceId) {
12919
13139
  super();
12920
13140
  this.supervisorInstanceId = supervisorInstanceId;
12921
13141
  this.workspaceId = workspaceId;
12922
13142
  }
13143
+ /**
13144
+ * Set the Browser MCP URL to pass to child daemons
13145
+ */
13146
+ setBrowserMcpUrl(url) {
13147
+ this.browserMcpUrl = url;
13148
+ }
12923
13149
  /**
12924
13150
  * Spawn a new daemon child process
12925
13151
  */
@@ -12967,9 +13193,11 @@ var init_child_manager = __esm({
12967
13193
  VIYV_SUPERVISOR_INSTANCE_ID: this.supervisorInstanceId,
12968
13194
  // Pass supervisor's workspaceId to ensure child daemons use the same workspace
12969
13195
  // (config file may have been updated since supervisor started)
12970
- ...this.workspaceId ? { VIYV_WORKSPACE_ID: this.workspaceId } : {}
13196
+ ...this.workspaceId ? { VIYV_WORKSPACE_ID: this.workspaceId } : {},
13197
+ // Pass Browser MCP URL so children share the supervisor's single instance
13198
+ ...this.browserMcpUrl ? { VIYV_BROWSER_MCP_URL: this.browserMcpUrl } : {}
12971
13199
  };
12972
- const child = spawn3(execPath, args2, {
13200
+ const child = spawn4(execPath, args2, {
12973
13201
  stdio: ["ignore", "inherit", "inherit"],
12974
13202
  env: childEnv,
12975
13203
  detached: false
@@ -13190,6 +13418,7 @@ var init_supervisor = __esm({
13190
13418
  init_daemon_configs();
13191
13419
  init_daemon_presets();
13192
13420
  init_child_manager();
13421
+ init_browser_mcp_process();
13193
13422
  DaemonSupervisor = class extends EventEmitter33 {
13194
13423
  state;
13195
13424
  instanceId;
@@ -13202,6 +13431,7 @@ var init_supervisor = __esm({
13202
13431
  shuttingDown = false;
13203
13432
  running = false;
13204
13433
  updateCommands = false;
13434
+ browserMcpProcess = null;
13205
13435
  constructor(options) {
13206
13436
  super();
13207
13437
  this.state = loadConfig();
@@ -13268,6 +13498,17 @@ var init_supervisor = __esm({
13268
13498
  } else {
13269
13499
  console.log(`[Supervisor] Found ${configs.length} daemon config(s) to start`);
13270
13500
  }
13501
+ try {
13502
+ this.browserMcpProcess = new BrowserMcpProcess();
13503
+ await this.browserMcpProcess.start();
13504
+ const browserUrl = this.browserMcpProcess.getUrl();
13505
+ if (browserUrl) {
13506
+ this.childManager.setBrowserMcpUrl(browserUrl);
13507
+ }
13508
+ } catch (error) {
13509
+ console.error("[Supervisor] Failed to start BrowserMcpProcess:", error);
13510
+ this.browserMcpProcess = null;
13511
+ }
13271
13512
  await this.connectToHub();
13272
13513
  if (configs.length > 0) {
13273
13514
  const results = await Promise.allSettled(
@@ -13588,6 +13829,14 @@ var init_supervisor = __esm({
13588
13829
  this.stopHeartbeat();
13589
13830
  this.cancelReconnect();
13590
13831
  await this.childManager.stopAll();
13832
+ if (this.browserMcpProcess) {
13833
+ try {
13834
+ await this.browserMcpProcess.stop();
13835
+ console.log("[Supervisor] BrowserMcpProcess stopped");
13836
+ } catch (error) {
13837
+ console.error("[Supervisor] Error stopping BrowserMcpProcess:", error);
13838
+ }
13839
+ }
13591
13840
  if (this.ws) {
13592
13841
  this.ws.close(1e3, "Supervisor shutdown");
13593
13842
  this.ws = null;
@@ -13643,7 +13892,7 @@ import { select as select2, confirm as confirm3, input as input3 } from "@inquir
13643
13892
  init_loader();
13644
13893
  init_types();
13645
13894
  import { EventEmitter as EventEmitter27 } from "events";
13646
- import { existsSync as existsSync33, mkdirSync as mkdirSync25 } from "fs";
13895
+ import { existsSync as existsSync33, mkdirSync as mkdirSync24 } from "fs";
13647
13896
  import { join as join34 } from "path";
13648
13897
  import { randomUUID as randomUUID18, createHash as createHash4 } from "crypto";
13649
13898
 
@@ -13878,7 +14127,7 @@ var LocalSocketServer = class _LocalSocketServer extends EventEmitter {
13878
14127
  };
13879
14128
 
13880
14129
  // src/socket/handlers.ts
13881
- var PACKAGE_VERSION = "0.1.8";
14130
+ var PACKAGE_VERSION = "0.1.9";
13882
14131
  function createSocketHandler(daemon) {
13883
14132
  return async (_clientId, message) => {
13884
14133
  switch (message.type) {
@@ -14897,13 +15146,6 @@ var MessageRouter = class {
14897
15146
  }
14898
15147
  };
14899
15148
 
14900
- // src/bridge/integration-message-handler.ts
14901
- init_daemon_configs();
14902
- init_types();
14903
- import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync6, readdirSync as readdirSync2, rmSync } from "fs";
14904
- import { homedir as homedir2 } from "os";
14905
- import { join as join3 } from "path";
14906
-
14907
15149
  // src/managers/slack-socket-manager.ts
14908
15150
  import { SocketModeClient } from "@slack/socket-mode";
14909
15151
  import { WebClient } from "@slack/web-api";
@@ -14912,10 +15154,10 @@ import { WebClient } from "@slack/web-api";
14912
15154
  init_dist();
14913
15155
  init_types();
14914
15156
  import {
14915
- existsSync as existsSync6,
14916
- mkdirSync as mkdirSync5,
14917
- readFileSync as readFileSync5,
14918
- writeFileSync as writeFileSync5,
15157
+ existsSync as existsSync5,
15158
+ mkdirSync as mkdirSync4,
15159
+ readFileSync as readFileSync4,
15160
+ writeFileSync as writeFileSync4,
14919
15161
  unlinkSync as unlinkSync2,
14920
15162
  readdirSync
14921
15163
  } from "fs";
@@ -14973,16 +15215,16 @@ var SecureVault = class {
14973
15215
  * Create directory with specified permissions if it doesn't exist
14974
15216
  */
14975
15217
  ensureDirectory(dir, mode) {
14976
- if (!existsSync6(dir)) {
14977
- mkdirSync5(dir, { recursive: true, mode });
15218
+ if (!existsSync5(dir)) {
15219
+ mkdirSync4(dir, { recursive: true, mode });
14978
15220
  }
14979
15221
  }
14980
15222
  /**
14981
15223
  * Load existing master key or generate a new one
14982
15224
  */
14983
15225
  loadOrGenerateMasterKey() {
14984
- if (existsSync6(this.keyPath)) {
14985
- const keyBase64 = readFileSync5(this.keyPath, "utf-8").trim();
15226
+ if (existsSync5(this.keyPath)) {
15227
+ const keyBase64 = readFileSync4(this.keyPath, "utf-8").trim();
14986
15228
  const key2 = Buffer.from(keyBase64, "base64");
14987
15229
  if (key2.length !== KEY_LENGTH) {
14988
15230
  throw new Error(
@@ -14992,7 +15234,7 @@ var SecureVault = class {
14992
15234
  return key2;
14993
15235
  }
14994
15236
  const key = randomBytes(KEY_LENGTH);
14995
- writeFileSync5(this.keyPath, key.toString("base64"), { mode: 384 });
15237
+ writeFileSync4(this.keyPath, key.toString("base64"), { mode: 384 });
14996
15238
  return key;
14997
15239
  }
14998
15240
  /**
@@ -15049,7 +15291,7 @@ var SecureVault = class {
15049
15291
  this.ensureInitialized();
15050
15292
  const configPath = this.getProviderConfigPath(provider);
15051
15293
  const encrypted = this.encrypt(JSON.stringify(config));
15052
- writeFileSync5(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
15294
+ writeFileSync4(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
15053
15295
  }
15054
15296
  /**
15055
15297
  * Get provider configuration
@@ -15057,11 +15299,11 @@ var SecureVault = class {
15057
15299
  async getProviderConfig(provider) {
15058
15300
  this.ensureInitialized();
15059
15301
  const configPath = this.getProviderConfigPath(provider);
15060
- if (!existsSync6(configPath)) {
15302
+ if (!existsSync5(configPath)) {
15061
15303
  return null;
15062
15304
  }
15063
15305
  try {
15064
- const content = readFileSync5(configPath, "utf-8");
15306
+ const content = readFileSync4(configPath, "utf-8");
15065
15307
  const encrypted = JSON.parse(content);
15066
15308
  const decrypted = this.decrypt(encrypted);
15067
15309
  return JSON.parse(decrypted);
@@ -15075,7 +15317,7 @@ var SecureVault = class {
15075
15317
  */
15076
15318
  async deleteProviderConfig(provider) {
15077
15319
  const configPath = this.getProviderConfigPath(provider);
15078
- if (existsSync6(configPath)) {
15320
+ if (existsSync5(configPath)) {
15079
15321
  unlinkSync2(configPath);
15080
15322
  }
15081
15323
  }
@@ -15109,18 +15351,18 @@ var SecureVault = class {
15109
15351
  useCustomClient
15110
15352
  }
15111
15353
  };
15112
- writeFileSync5(tokenPath, JSON.stringify(storedData, null, 2), { mode: 384 });
15354
+ writeFileSync4(tokenPath, JSON.stringify(storedData, null, 2), { mode: 384 });
15113
15355
  }
15114
15356
  /**
15115
15357
  * Get stored token data (internal use)
15116
15358
  */
15117
15359
  async getStoredTokenData(provider) {
15118
15360
  const tokenPath = this.getTokenPath(provider);
15119
- if (!existsSync6(tokenPath)) {
15361
+ if (!existsSync5(tokenPath)) {
15120
15362
  return null;
15121
15363
  }
15122
15364
  try {
15123
- const content = readFileSync5(tokenPath, "utf-8");
15365
+ const content = readFileSync4(tokenPath, "utf-8");
15124
15366
  return JSON.parse(content);
15125
15367
  } catch (error) {
15126
15368
  console.error(`Failed to read token data for ${provider}:`, error);
@@ -15141,7 +15383,7 @@ var SecureVault = class {
15141
15383
  const tokens = JSON.parse(decrypted);
15142
15384
  storedData.metadata.lastUsedAt = (/* @__PURE__ */ new Date()).toISOString();
15143
15385
  const tokenPath = this.getTokenPath(provider);
15144
- writeFileSync5(tokenPath, JSON.stringify(storedData, null, 2), { mode: 384 });
15386
+ writeFileSync4(tokenPath, JSON.stringify(storedData, null, 2), { mode: 384 });
15145
15387
  return tokens;
15146
15388
  } catch (error) {
15147
15389
  console.error(`Failed to decrypt tokens for ${provider}:`, error);
@@ -15153,7 +15395,7 @@ var SecureVault = class {
15153
15395
  */
15154
15396
  async deleteTokens(provider) {
15155
15397
  const tokenPath = this.getTokenPath(provider);
15156
- if (existsSync6(tokenPath)) {
15398
+ if (existsSync5(tokenPath)) {
15157
15399
  unlinkSync2(tokenPath);
15158
15400
  }
15159
15401
  }
@@ -15162,7 +15404,7 @@ var SecureVault = class {
15162
15404
  */
15163
15405
  async hasTokens(provider) {
15164
15406
  const tokenPath = this.getTokenPath(provider);
15165
- return existsSync6(tokenPath);
15407
+ return existsSync5(tokenPath);
15166
15408
  }
15167
15409
  /**
15168
15410
  * Get token metadata (without decrypting tokens)
@@ -15196,7 +15438,7 @@ var SecureVault = class {
15196
15438
  // Always true for Slack tokens
15197
15439
  }
15198
15440
  };
15199
- writeFileSync5(tokenPath, JSON.stringify(storedData, null, 2), { mode: 384 });
15441
+ writeFileSync4(tokenPath, JSON.stringify(storedData, null, 2), { mode: 384 });
15200
15442
  }
15201
15443
  /**
15202
15444
  * Get Slack Socket Mode tokens
@@ -15212,7 +15454,7 @@ var SecureVault = class {
15212
15454
  const tokens = JSON.parse(decrypted);
15213
15455
  storedData.metadata.lastUsedAt = (/* @__PURE__ */ new Date()).toISOString();
15214
15456
  const tokenPath = this.getTokenPath("slack");
15215
- writeFileSync5(tokenPath, JSON.stringify(storedData, null, 2), { mode: 384 });
15457
+ writeFileSync4(tokenPath, JSON.stringify(storedData, null, 2), { mode: 384 });
15216
15458
  return tokens;
15217
15459
  } catch (error) {
15218
15460
  console.error("Failed to decrypt Slack tokens:", error);
@@ -15252,7 +15494,7 @@ var SecureVault = class {
15252
15494
  storedData.encrypted = this.encrypt(JSON.stringify(newTokens));
15253
15495
  storedData.metadata.lastUsedAt = (/* @__PURE__ */ new Date()).toISOString();
15254
15496
  const tokenPath = this.getTokenPath(provider);
15255
- writeFileSync5(tokenPath, JSON.stringify(storedData, null, 2), { mode: 384 });
15497
+ writeFileSync4(tokenPath, JSON.stringify(storedData, null, 2), { mode: 384 });
15256
15498
  }
15257
15499
  // =====================
15258
15500
  // Status Methods
@@ -15299,7 +15541,7 @@ var SecureVault = class {
15299
15541
  */
15300
15542
  async listConnectedProviders() {
15301
15543
  const providers = [];
15302
- if (existsSync6(this.tokensDir)) {
15544
+ if (existsSync5(this.tokensDir)) {
15303
15545
  const files = readdirSync(this.tokensDir);
15304
15546
  for (const file of files) {
15305
15547
  if (file.endsWith(".enc")) {
@@ -16279,7 +16521,6 @@ var IntegrationMessageHandler = class {
16279
16521
  messageRouter;
16280
16522
  daemonName;
16281
16523
  getSlackSocketManager;
16282
- getDaemon;
16283
16524
  oauthManager = null;
16284
16525
  initialized = false;
16285
16526
  onConnected;
@@ -16289,7 +16530,6 @@ var IntegrationMessageHandler = class {
16289
16530
  this.messageRouter = config.messageRouter;
16290
16531
  this.daemonName = config.daemonName;
16291
16532
  this.getSlackSocketManager = config.getSlackSocketManager;
16292
- this.getDaemon = config.getDaemon;
16293
16533
  this.onConnected = config.onConnected;
16294
16534
  this.onDisconnected = config.onDisconnected;
16295
16535
  this.onSlackSetup = config.onSlackSetup;
@@ -16387,14 +16627,6 @@ var IntegrationMessageHandler = class {
16387
16627
  "slack.updateMessage.request",
16388
16628
  this.handleSlackUpdateMessageRequest.bind(this)
16389
16629
  );
16390
- this.messageRouter.registerHandler(
16391
- "chrome.profiles.list.request",
16392
- this.handleChromeProfilesListRequest.bind(this)
16393
- );
16394
- this.messageRouter.registerHandler(
16395
- "chrome.profile.set.request",
16396
- this.handleChromeProfileSetRequest.bind(this)
16397
- );
16398
16630
  }
16399
16631
  /**
16400
16632
  * Handle OAuth preset response from Hub
@@ -16784,107 +17016,6 @@ var IntegrationMessageHandler = class {
16784
17016
  });
16785
17017
  }
16786
17018
  }
16787
- /**
16788
- * Handle Chrome profiles list request
16789
- */
16790
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: FS scanning logic
16791
- async handleChromeProfilesListRequest(envelope, respond) {
16792
- const payload = envelope.payload;
16793
- const profiles = [];
16794
- const managedDir = join3(getConfigDir(), "chrome-profiles");
16795
- if (existsSync7(managedDir)) {
16796
- for (const entry of readdirSync2(managedDir, { withFileTypes: true })) {
16797
- if (entry.isDirectory()) {
16798
- profiles.push({
16799
- type: "managed",
16800
- name: entry.name,
16801
- path: join3(managedDir, entry.name)
16802
- });
16803
- }
16804
- }
16805
- }
16806
- const chromeDir = getChromeUserDataDir();
16807
- if (chromeDir && existsSync7(chromeDir)) {
16808
- for (const entry of readdirSync2(chromeDir, { withFileTypes: true })) {
16809
- if (!entry.isDirectory()) continue;
16810
- const prefsPath = join3(chromeDir, entry.name, "Preferences");
16811
- if (existsSync7(prefsPath)) {
16812
- try {
16813
- const prefs = JSON.parse(readFileSync6(prefsPath, "utf-8"));
16814
- const displayName = prefs.profile?.name || entry.name;
16815
- profiles.push({
16816
- type: "chrome",
16817
- name: displayName,
16818
- path: join3(chromeDir, entry.name)
16819
- });
16820
- } catch {
16821
- }
16822
- }
16823
- }
16824
- }
16825
- const daemonConfig = this.daemonName ? getDaemonConfig(this.daemonName) : void 0;
16826
- respond({
16827
- profiles,
16828
- currentProfilePath: daemonConfig?.chromeProfilePath,
16829
- _originNodeId: payload._originNodeId
16830
- });
16831
- }
16832
- /**
16833
- * Handle Chrome profile set request
16834
- */
16835
- async handleChromeProfileSetRequest(envelope, respond) {
16836
- const payload = envelope.payload;
16837
- if (payload.deleteProfileName) {
16838
- const name = payload.deleteProfileName;
16839
- if (!isValidProfileName(name)) {
16840
- respond({
16841
- success: false,
16842
- error: "Invalid profile name",
16843
- _originNodeId: payload._originNodeId
16844
- });
16845
- return;
16846
- }
16847
- const targetDir = join3(getConfigDir(), "chrome-profiles", name);
16848
- if (existsSync7(targetDir)) {
16849
- rmSync(targetDir, { recursive: true, force: true });
16850
- }
16851
- if (this.daemonName) {
16852
- const currentConfig = getDaemonConfig(this.daemonName);
16853
- if (currentConfig?.chromeProfilePath === targetDir) {
16854
- updateDaemonConfig(this.daemonName, { chromeProfilePath: void 0 });
16855
- this.getDaemon?.()?.setChromeProfilePath(void 0);
16856
- }
16857
- }
16858
- respond({ success: true, _originNodeId: payload._originNodeId });
16859
- return;
16860
- }
16861
- let finalProfilePath = payload.profilePath;
16862
- if (payload.createNewName) {
16863
- const name = payload.createNewName.trim();
16864
- if (!name || !isValidProfileName(name)) {
16865
- respond({
16866
- success: false,
16867
- error: "Invalid profile name",
16868
- _originNodeId: payload._originNodeId
16869
- });
16870
- return;
16871
- }
16872
- const managedDir = join3(getConfigDir(), "chrome-profiles", name);
16873
- mkdirSync6(managedDir, { recursive: true });
16874
- finalProfilePath = managedDir;
16875
- }
16876
- if (this.daemonName) {
16877
- updateDaemonConfig(this.daemonName, {
16878
- chromeProfilePath: finalProfilePath || void 0
16879
- });
16880
- }
16881
- this.getDaemon?.()?.setChromeProfilePath(finalProfilePath || void 0);
16882
- respond({
16883
- success: true,
16884
- profilePath: finalProfilePath || void 0,
16885
- _originNodeId: payload._originNodeId
16886
- });
16887
- }
16888
17019
  /**
16889
17020
  * Cleanup resources
16890
17021
  */
@@ -16901,8 +17032,6 @@ var IntegrationMessageHandler = class {
16901
17032
  this.messageRouter.unregisterHandler("slack.disconnect.request");
16902
17033
  this.messageRouter.unregisterHandler("slack.postMessage.request");
16903
17034
  this.messageRouter.unregisterHandler("slack.updateMessage.request");
16904
- this.messageRouter.unregisterHandler("chrome.profiles.list.request");
16905
- this.messageRouter.unregisterHandler("chrome.profile.set.request");
16906
17035
  for (const pending of this.pendingPresetRequests.values()) {
16907
17036
  clearTimeout(pending.timeout);
16908
17037
  }
@@ -16913,26 +17042,6 @@ var IntegrationMessageHandler = class {
16913
17042
  this.initialized = false;
16914
17043
  }
16915
17044
  };
16916
- function isValidProfileName(name) {
16917
- if (name.includes("/") || name.includes("\\") || name === ".." || name === ".") return false;
16918
- if (/[<>:"|?*\x00-\x1F]/.test(name)) return false;
16919
- if (!name.trim()) return false;
16920
- return true;
16921
- }
16922
- function getChromeUserDataDir() {
16923
- const platform = process.platform;
16924
- const home = homedir2();
16925
- if (platform === "darwin") {
16926
- return join3(home, "Library", "Application Support", "Google", "Chrome");
16927
- }
16928
- if (platform === "linux") {
16929
- return join3(home, ".config", "google-chrome");
16930
- }
16931
- if (platform === "win32") {
16932
- return join3(home, "AppData", "Local", "Google", "Chrome", "User Data");
16933
- }
16934
- return null;
16935
- }
16936
17045
  async function createIntegrationMessageHandler(config) {
16937
17046
  const handler = new IntegrationMessageHandler(config);
16938
17047
  await handler.initialize();
@@ -17693,6 +17802,7 @@ var IpcHandler = class extends EventEmitter4 {
17693
17802
  workspaceTaskToolsServer = null;
17694
17803
  // Google MCP server URL callback for injecting Google tools into agent configs
17695
17804
  googleMcpUrlCallback;
17805
+ browserMcpUrlCallback;
17696
17806
  // Track taskId → cloudCorrelationId for delegation completion tracking
17697
17807
  // Used to wait for child delegations before sending task.execution.completed
17698
17808
  taskIdToCloudCorrelationMap = /* @__PURE__ */ new Map();
@@ -17837,23 +17947,26 @@ var IpcHandler = class extends EventEmitter4 {
17837
17947
  setGoogleMcpUrlCallback(callback) {
17838
17948
  this.googleMcpUrlCallback = callback;
17839
17949
  }
17950
+ setBrowserMcpUrlCallback(callback) {
17951
+ this.browserMcpUrlCallback = callback;
17952
+ }
17840
17953
  /**
17841
17954
  * Write MCP config to agent's workspace .mcp.json file
17842
17955
  * This enables the UI to display MCP servers for child agents
17843
17956
  * IMPORTANT: This MERGES with existing config to preserve MCP servers
17844
- * like chrome-devtools that were set up during daemon startup
17957
+ * like viyv-browser that were set up during daemon startup
17845
17958
  */
17846
17959
  async writeMcpConfigToWorkspace(cwd, mcpServers) {
17847
17960
  if (!mcpServers || Object.keys(mcpServers).length === 0) {
17848
17961
  return;
17849
17962
  }
17850
17963
  try {
17851
- const { writeFileSync: writeFileSync27, readFileSync: readFileSync30, existsSync: existsSync38, mkdirSync: mkdirSync28 } = await import("fs");
17964
+ const { writeFileSync: writeFileSync28, readFileSync: readFileSync30, existsSync: existsSync38, mkdirSync: mkdirSync27 } = await import("fs");
17852
17965
  const { dirname: dirname13 } = await import("path");
17853
17966
  const mcpConfigPath = `${cwd}/.mcp.json`;
17854
17967
  const dir = dirname13(mcpConfigPath);
17855
17968
  if (!existsSync38(dir)) {
17856
- mkdirSync28(dir, { recursive: true });
17969
+ mkdirSync27(dir, { recursive: true });
17857
17970
  }
17858
17971
  let existingMcpServers = {};
17859
17972
  if (existsSync38(mcpConfigPath)) {
@@ -17863,13 +17976,14 @@ var IpcHandler = class extends EventEmitter4 {
17863
17976
  } catch {
17864
17977
  }
17865
17978
  }
17979
+ delete existingMcpServers["chrome-devtools"];
17866
17980
  const mcpConfig = {
17867
17981
  mcpServers: {
17868
17982
  ...existingMcpServers,
17869
17983
  ...mcpServers
17870
17984
  }
17871
17985
  };
17872
- writeFileSync27(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
17986
+ writeFileSync28(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
17873
17987
  console.log(`[IpcHandler] Updated MCP config at ${mcpConfigPath} with ${Object.keys(mcpConfig.mcpServers).length} servers`);
17874
17988
  } catch (error) {
17875
17989
  console.warn(`[IpcHandler] Failed to write MCP config to ${cwd}:`, error);
@@ -18269,6 +18383,21 @@ ${messageWithContext}`;
18269
18383
  };
18270
18384
  }
18271
18385
  }
18386
+ if (this.browserMcpUrlCallback) {
18387
+ const browserMcpUrl = this.browserMcpUrlCallback();
18388
+ if (browserMcpUrl) {
18389
+ modifiedAgentConfig = {
18390
+ ...modifiedAgentConfig,
18391
+ mcpServers: {
18392
+ ...modifiedAgentConfig?.mcpServers,
18393
+ "viyv-browser": {
18394
+ type: "sse",
18395
+ url: `${browserMcpUrl}/sse`
18396
+ }
18397
+ }
18398
+ };
18399
+ }
18400
+ }
18272
18401
  const agentCwd = process2.getCwd();
18273
18402
  if (agentCwd && modifiedAgentConfig?.mcpServers) {
18274
18403
  void this.writeMcpConfigToWorkspace(agentCwd, modifiedAgentConfig.mcpServers);
@@ -19394,6 +19523,21 @@ ${userResponseText}
19394
19523
  };
19395
19524
  }
19396
19525
  }
19526
+ if (this.browserMcpUrlCallback) {
19527
+ const browserMcpUrl = this.browserMcpUrlCallback();
19528
+ if (browserMcpUrl) {
19529
+ agentConfig = {
19530
+ ...agentConfig,
19531
+ mcpServers: {
19532
+ ...agentConfig?.mcpServers,
19533
+ "viyv-browser": {
19534
+ type: "sse",
19535
+ url: `${browserMcpUrl}/sse`
19536
+ }
19537
+ }
19538
+ };
19539
+ }
19540
+ }
19397
19541
  const resultPromise = new Promise((resolve6, reject) => {
19398
19542
  let targetProcess = null;
19399
19543
  let targetProcessId = null;
@@ -19565,11 +19709,11 @@ ${message}`;
19565
19709
  import { EventEmitter as EventEmitter5 } from "events";
19566
19710
 
19567
19711
  // src/scheduler/local-schedule-store.ts
19568
- import { existsSync as existsSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
19569
- import { dirname as dirname4, join as join4 } from "path";
19570
- import { homedir as homedir3 } from "os";
19571
- import { randomUUID as randomUUID3 } from "crypto";
19572
- var DEFAULT_STORAGE_DIR = join4(homedir3(), ".viyv-agent");
19712
+ import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
19713
+ import { dirname as dirname3, join as join3 } from "path";
19714
+ import { homedir as homedir2 } from "os";
19715
+ import { randomUUID as randomUUID2 } from "crypto";
19716
+ var DEFAULT_STORAGE_DIR = join3(homedir2(), ".viyv-agent");
19573
19717
  var DEFAULT_SCHEDULES_FILE = "schedules.json";
19574
19718
  var CURRENT_SCHEMA_VERSION = 1;
19575
19719
  var MAX_EXECUTION_HISTORY = 100;
@@ -19579,18 +19723,18 @@ var LocalScheduleStore = class {
19579
19723
  constructor(options) {
19580
19724
  const storageDir = options?.storageDir ?? DEFAULT_STORAGE_DIR;
19581
19725
  const fileName = options?.fileName ?? DEFAULT_SCHEDULES_FILE;
19582
- this.filePath = join4(storageDir, fileName);
19726
+ this.filePath = join3(storageDir, fileName);
19583
19727
  }
19584
19728
  /**
19585
19729
  * Initialize the store - creates directory and file if needed
19586
19730
  */
19587
19731
  async initialize() {
19588
- const dir = dirname4(this.filePath);
19589
- if (!existsSync8(dir)) {
19590
- mkdirSync7(dir, { recursive: true });
19732
+ const dir = dirname3(this.filePath);
19733
+ if (!existsSync6(dir)) {
19734
+ mkdirSync5(dir, { recursive: true });
19591
19735
  console.log(`[LocalScheduleStore] Created directory: ${dir}`);
19592
19736
  }
19593
- if (!existsSync8(this.filePath)) {
19737
+ if (!existsSync6(this.filePath)) {
19594
19738
  this.data = this.createEmptyFile();
19595
19739
  await this.save();
19596
19740
  console.log(`[LocalScheduleStore] Created new schedules file: ${this.filePath}`);
@@ -19603,7 +19747,7 @@ var LocalScheduleStore = class {
19603
19747
  */
19604
19748
  async load() {
19605
19749
  try {
19606
- const content = readFileSync7(this.filePath, "utf-8");
19750
+ const content = readFileSync5(this.filePath, "utf-8");
19607
19751
  const parsed = JSON.parse(content);
19608
19752
  if (parsed.version !== CURRENT_SCHEMA_VERSION) {
19609
19753
  this.data = this.migrate(parsed);
@@ -19630,20 +19774,20 @@ var LocalScheduleStore = class {
19630
19774
  throw new Error("LocalScheduleStore not initialized");
19631
19775
  }
19632
19776
  try {
19633
- const dir = dirname4(this.filePath);
19634
- if (!existsSync8(dir)) {
19635
- mkdirSync7(dir, { recursive: true });
19777
+ const dir = dirname3(this.filePath);
19778
+ if (!existsSync6(dir)) {
19779
+ mkdirSync5(dir, { recursive: true });
19636
19780
  }
19637
19781
  const uniqueSuffix = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
19638
19782
  const tempPath = `${this.filePath}.tmp.${uniqueSuffix}`;
19639
19783
  const content = JSON.stringify(this.data, null, 2);
19640
- writeFileSync6(tempPath, content, "utf-8");
19641
- const { renameSync: renameSync5, unlinkSync: unlinkSync11 } = await import("fs");
19784
+ writeFileSync5(tempPath, content, "utf-8");
19785
+ const { renameSync: renameSync5, unlinkSync: unlinkSync12 } = await import("fs");
19642
19786
  try {
19643
19787
  renameSync5(tempPath, this.filePath);
19644
19788
  } catch (renameError) {
19645
19789
  try {
19646
- unlinkSync11(tempPath);
19790
+ unlinkSync12(tempPath);
19647
19791
  } catch {
19648
19792
  }
19649
19793
  throw renameError;
@@ -19713,7 +19857,7 @@ var LocalScheduleStore = class {
19713
19857
  const now = (/* @__PURE__ */ new Date()).toISOString();
19714
19858
  const schedule = {
19715
19859
  ...config,
19716
- id: randomUUID3(),
19860
+ id: randomUUID2(),
19717
19861
  state: {
19718
19862
  totalRuns: 0,
19719
19863
  successfulRuns: 0,
@@ -21519,16 +21663,16 @@ var ORCHESTRATION_TOOLS = [
21519
21663
 
21520
21664
  // src/mcp/orchestration-tools-server.ts
21521
21665
  import http2 from "http";
21522
- import { existsSync as existsSync17, mkdirSync as mkdirSync15, writeFileSync as writeFileSync14 } from "fs";
21523
- import { join as join17 } from "path";
21524
- import { homedir as homedir11 } from "os";
21666
+ import { existsSync as existsSync15, mkdirSync as mkdirSync13, writeFileSync as writeFileSync13 } from "fs";
21667
+ import { join as join16 } from "path";
21668
+ import { homedir as homedir10 } from "os";
21525
21669
 
21526
21670
  // src/orchestration/policy-merger.ts
21527
21671
  init_dist();
21528
21672
  import * as fs from "fs";
21529
21673
  import * as path from "path";
21530
21674
  import * as yaml from "yaml";
21531
- import { homedir as homedir4 } from "os";
21675
+ import { homedir as homedir3 } from "os";
21532
21676
  var PolicyMerger = class {
21533
21677
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
21534
21678
  constructor(_orchestratorCwd) {
@@ -21538,7 +21682,7 @@ var PolicyMerger = class {
21538
21682
  * Uses global ~/.viyv-agent/policies to avoid nested paths
21539
21683
  */
21540
21684
  getGlobalPolicyPath() {
21541
- return path.join(homedir4(), ".viyv-agent", "policies", "global.yaml");
21685
+ return path.join(homedir3(), ".viyv-agent", "policies", "global.yaml");
21542
21686
  }
21543
21687
  /**
21544
21688
  * Get the default path for project policy
@@ -21546,7 +21690,7 @@ var PolicyMerger = class {
21546
21690
  */
21547
21691
  getProjectPolicyPath(projectId) {
21548
21692
  const safeProjectId = projectId || "default";
21549
- return path.join(homedir4(), ".viyv-agent", "policies", `${safeProjectId}.yaml`);
21693
+ return path.join(homedir3(), ".viyv-agent", "policies", `${safeProjectId}.yaml`);
21550
21694
  }
21551
21695
  /**
21552
21696
  * Load a policy document from a YAML file
@@ -21758,8 +21902,8 @@ init_dist();
21758
21902
  import * as fs2 from "fs";
21759
21903
  import * as path2 from "path";
21760
21904
  import * as yaml2 from "yaml";
21761
- import { randomUUID as randomUUID4 } from "crypto";
21762
- import { homedir as homedir5 } from "os";
21905
+ import { randomUUID as randomUUID3 } from "crypto";
21906
+ import { homedir as homedir4 } from "os";
21763
21907
  var DEFAULT_AGENT_TEMPLATE_ID = "claude-code-agent";
21764
21908
  var AGENT_ROLE_CONFIGS = [
21765
21909
  {
@@ -22008,7 +22152,7 @@ var ManifestGenerator = class {
22008
22152
  */
22009
22153
  getManifestDir(projectId) {
22010
22154
  const safeProjectId = projectId || "default";
22011
- return path2.join(homedir5(), ".viyv-agent", "manifests", safeProjectId);
22155
+ return path2.join(homedir4(), ".viyv-agent", "manifests", safeProjectId);
22012
22156
  }
22013
22157
  /**
22014
22158
  * Get manifest file path
@@ -22022,7 +22166,7 @@ var ManifestGenerator = class {
22022
22166
  */
22023
22167
  getTopologyPath(projectId) {
22024
22168
  const safeProjectId = projectId || "default";
22025
- return path2.join(homedir5(), ".viyv-agent", "topologies", safeProjectId, "topology.yaml");
22169
+ return path2.join(homedir4(), ".viyv-agent", "topologies", safeProjectId, "topology.yaml");
22026
22170
  }
22027
22171
  /**
22028
22172
  * Load topology from file
@@ -22190,7 +22334,7 @@ var ManifestGenerator = class {
22190
22334
  async generateManifest(params) {
22191
22335
  const {
22192
22336
  projectDescription,
22193
- projectId = randomUUID4().slice(0, 8),
22337
+ projectId = randomUUID3().slice(0, 8),
22194
22338
  projectName = `Project ${projectId}`,
22195
22339
  basePath,
22196
22340
  orchestratorNodeId = "orchestrator",
@@ -22336,20 +22480,20 @@ init_dist();
22336
22480
  import * as fs7 from "fs";
22337
22481
  import * as path8 from "path";
22338
22482
  import * as yaml3 from "yaml";
22339
- import { randomUUID as randomUUID6 } from "crypto";
22340
- import { homedir as homedir10 } from "os";
22483
+ import { randomUUID as randomUUID5 } from "crypto";
22484
+ import { homedir as homedir9 } from "os";
22341
22485
 
22342
22486
  // src/orchestration/setup-ticket-manager.ts
22343
22487
  init_dist();
22344
22488
  import * as fs4 from "fs";
22345
22489
  import * as path4 from "path";
22346
- import { randomUUID as randomUUID5 } from "crypto";
22347
- import { homedir as homedir7 } from "os";
22490
+ import { randomUUID as randomUUID4 } from "crypto";
22491
+ import { homedir as homedir6 } from "os";
22348
22492
  var SetupTicketManager = class {
22349
22493
  ticketsDir;
22350
22494
  memoryCache = /* @__PURE__ */ new Map();
22351
22495
  constructor(_orchestratorCwd) {
22352
- this.ticketsDir = path4.join(homedir7(), ".viyv-agent", "setup-tickets");
22496
+ this.ticketsDir = path4.join(homedir6(), ".viyv-agent", "setup-tickets");
22353
22497
  }
22354
22498
  /**
22355
22499
  * Initialize the manager and restore tickets from disk
@@ -22412,7 +22556,7 @@ var SetupTicketManager = class {
22412
22556
  // 10 minutes default
22413
22557
  maxRetries = 3
22414
22558
  } = params;
22415
- const ticketId = `ticket-${randomUUID5().slice(0, 8)}`;
22559
+ const ticketId = `ticket-${randomUUID4().slice(0, 8)}`;
22416
22560
  const now = (/* @__PURE__ */ new Date()).toISOString();
22417
22561
  const ticket = {
22418
22562
  ticketId,
@@ -22633,7 +22777,7 @@ function getSetupTicketManager(orchestratorCwd) {
22633
22777
  // src/orchestration/soft-stop-manager.ts
22634
22778
  import * as fs5 from "fs";
22635
22779
  import * as path5 from "path";
22636
- import { homedir as homedir8 } from "os";
22780
+ import { homedir as homedir7 } from "os";
22637
22781
  var DEFAULT_SOFT_STOP_OPTIONS = {
22638
22782
  gracePeriodMs: 3e4,
22639
22783
  // 30 seconds for graceful shutdown
@@ -22644,14 +22788,14 @@ var DEFAULT_SOFT_STOP_OPTIONS = {
22644
22788
  // src/orchestration/context-manager.ts
22645
22789
  import * as fs6 from "fs";
22646
22790
  import * as path6 from "path";
22647
- import { homedir as homedir9 } from "os";
22791
+ import { homedir as homedir8 } from "os";
22648
22792
  var ContextManager = class {
22649
22793
  baseDir;
22650
22794
  contextsDir;
22651
22795
  sessionsDir;
22652
22796
  knowledgeDir;
22653
22797
  constructor(_orchestratorCwd) {
22654
- this.baseDir = path6.join(homedir9(), ".viyv-agent");
22798
+ this.baseDir = path6.join(homedir8(), ".viyv-agent");
22655
22799
  this.contextsDir = path6.join(this.baseDir, "contexts");
22656
22800
  this.sessionsDir = path6.join(this.baseDir, "sessions");
22657
22801
  this.knowledgeDir = path6.join(this.baseDir, "knowledge");
@@ -23389,7 +23533,7 @@ var ManifestApplier = class {
23389
23533
  };
23390
23534
  try {
23391
23535
  const contextMarkdown = this.contextManager.generateContextContent(contextContent);
23392
- const globalContextDir = path8.join(homedir10(), ".viyv-agent", "contexts", targetNodeId);
23536
+ const globalContextDir = path8.join(homedir9(), ".viyv-agent", "contexts", targetNodeId);
23393
23537
  if (!fs7.existsSync(globalContextDir)) {
23394
23538
  fs7.mkdirSync(globalContextDir, { recursive: true });
23395
23539
  }
@@ -23480,14 +23624,14 @@ var ManifestApplier = class {
23480
23624
  * Uses global ~/.viyv-agent/logs/operations to avoid nested paths
23481
23625
  */
23482
23626
  getOperationsLogDir() {
23483
- return path8.join(homedir10(), ".viyv-agent", "logs", "operations");
23627
+ return path8.join(homedir9(), ".viyv-agent", "logs", "operations");
23484
23628
  }
23485
23629
  /**
23486
23630
  * Get setup tickets directory
23487
23631
  * Uses global ~/.viyv-agent/setup-tickets to avoid nested paths
23488
23632
  */
23489
23633
  getSetupTicketsDir() {
23490
- return path8.join(homedir10(), ".viyv-agent", "setup-tickets");
23634
+ return path8.join(homedir9(), ".viyv-agent", "setup-tickets");
23491
23635
  }
23492
23636
  /**
23493
23637
  * Get topology directory
@@ -23496,7 +23640,7 @@ var ManifestApplier = class {
23496
23640
  */
23497
23641
  getTopologyDir(projectId) {
23498
23642
  const safeProjectId = projectId || "default";
23499
- return path8.join(homedir10(), ".viyv-agent", "topologies", safeProjectId);
23643
+ return path8.join(homedir9(), ".viyv-agent", "topologies", safeProjectId);
23500
23644
  }
23501
23645
  /**
23502
23646
  * Load existing topology if it exists
@@ -23522,7 +23666,7 @@ var ManifestApplier = class {
23522
23666
  */
23523
23667
  getManifestDir(projectId) {
23524
23668
  const safeProjectId = projectId || "default";
23525
- return path8.join(homedir10(), ".viyv-agent", "manifests", safeProjectId);
23669
+ return path8.join(homedir9(), ".viyv-agent", "manifests", safeProjectId);
23526
23670
  }
23527
23671
  /**
23528
23672
  * Delete manifest file after successful apply
@@ -23622,7 +23766,7 @@ var ManifestApplier = class {
23622
23766
  * Update topology agent status from 'setup_pending' to 'running'
23623
23767
  */
23624
23768
  updateTopologyAgentStatusToRunning(manifestAgentId, nodeId) {
23625
- const topologiesBaseDir = path8.join(homedir10(), ".viyv-agent", "topologies");
23769
+ const topologiesBaseDir = path8.join(homedir9(), ".viyv-agent", "topologies");
23626
23770
  if (!fs7.existsSync(topologiesBaseDir)) {
23627
23771
  console.warn(`[ManifestApplier] Topologies directory not found: ${topologiesBaseDir}`);
23628
23772
  return;
@@ -23755,7 +23899,7 @@ var ManifestApplier = class {
23755
23899
  * Apply manifest (main entry point)
23756
23900
  */
23757
23901
  async applyManifest(manifest, dryRun = false) {
23758
- const operationId = `op-${randomUUID6().slice(0, 8)}`;
23902
+ const operationId = `op-${randomUUID5().slice(0, 8)}`;
23759
23903
  const orchestratorNodeId = "orchestrator-daemon";
23760
23904
  console.log(`[ManifestApplier] Starting operation ${operationId}`);
23761
23905
  const currentTopology = this.loadTopology(manifest.projectId);
@@ -24064,7 +24208,7 @@ var ManifestApplier = class {
24064
24208
  init_dist();
24065
24209
 
24066
24210
  // src/orchestration/delegation-tracker.ts
24067
- import { randomUUID as randomUUID7 } from "crypto";
24211
+ import { randomUUID as randomUUID6 } from "crypto";
24068
24212
  var DelegationTracker = class {
24069
24213
  delegations = /* @__PURE__ */ new Map();
24070
24214
  correlationToDelegationMap = /* @__PURE__ */ new Map();
@@ -24092,7 +24236,7 @@ var DelegationTracker = class {
24092
24236
  * Create a new delegation record
24093
24237
  */
24094
24238
  createDelegation(params) {
24095
- const delegationId = randomUUID7();
24239
+ const delegationId = randomUUID6();
24096
24240
  const record = {
24097
24241
  delegationId,
24098
24242
  targetNodeId: params.targetNodeId,
@@ -24305,7 +24449,7 @@ var DelegationTracker = class {
24305
24449
  };
24306
24450
 
24307
24451
  // src/orchestration/completion-notification-queue.ts
24308
- import { randomUUID as randomUUID8 } from "crypto";
24452
+ import { randomUUID as randomUUID7 } from "crypto";
24309
24453
  var CompletionNotificationQueue = class {
24310
24454
  notifications = /* @__PURE__ */ new Map();
24311
24455
  pendingIds = [];
@@ -24326,7 +24470,7 @@ var CompletionNotificationQueue = class {
24326
24470
  */
24327
24471
  push(notification) {
24328
24472
  if (!notification.notificationId) {
24329
- notification.notificationId = randomUUID8();
24473
+ notification.notificationId = randomUUID7();
24330
24474
  }
24331
24475
  this.notifications.set(notification.delegationId, notification);
24332
24476
  this.pendingIds.push(notification.delegationId);
@@ -25712,7 +25856,7 @@ var OrchestrationToolsServer = class _OrchestrationToolsServer {
25712
25856
  const fs16 = await import("fs");
25713
25857
  const path18 = await import("path");
25714
25858
  const orchestratorId = this.daemon.getRuntimeState().instanceId;
25715
- const contextDir = path18.join(homedir11(), ".viyv-agent", "contexts", orchestratorId);
25859
+ const contextDir = path18.join(homedir10(), ".viyv-agent", "contexts", orchestratorId);
25716
25860
  const contextPath = path18.join(contextDir, "context.md");
25717
25861
  if (!fs16.existsSync(contextDir)) {
25718
25862
  fs16.mkdirSync(contextDir, { recursive: true });
@@ -25913,10 +26057,10 @@ ${content}
25913
26057
  }
25914
26058
  try {
25915
26059
  const orchestratorCwd = this.daemon.getOrchestratorCwd() || process.cwd();
25916
- const commandDir = join17(orchestratorCwd, ".claude", "commands", "user", category);
25917
- const commandPath = join17(commandDir, `${name}.md`);
25918
- if (!existsSync17(commandDir)) {
25919
- mkdirSync15(commandDir, { recursive: true });
26060
+ const commandDir = join16(orchestratorCwd, ".claude", "commands", "user", category);
26061
+ const commandPath = join16(commandDir, `${name}.md`);
26062
+ if (!existsSync15(commandDir)) {
26063
+ mkdirSync13(commandDir, { recursive: true });
25920
26064
  }
25921
26065
  const frontmatterParts = [
25922
26066
  "---",
@@ -25931,7 +26075,7 @@ ${content}
25931
26075
  const fullContent = `${frontmatter}
25932
26076
 
25933
26077
  ${content}`;
25934
- writeFileSync14(commandPath, fullContent, "utf-8");
26078
+ writeFileSync13(commandPath, fullContent, "utf-8");
25935
26079
  const commandId = `user:${category}:${name}`;
25936
26080
  console.log(`[OrchestrationToolsServer] Created user command: ${commandId} at ${commandPath}`);
25937
26081
  return {
@@ -25990,19 +26134,19 @@ ${content}`;
25990
26134
  error: `Unknown command preset: ${commandPreset}. Available: ${available}`
25991
26135
  };
25992
26136
  }
25993
- const commandsDir = join17(childCwd, ".claude", "commands");
26137
+ const commandsDir = join16(childCwd, ".claude", "commands");
25994
26138
  const addedCommands = [];
25995
26139
  const removedCommands = [];
25996
26140
  let appliedPreset;
25997
26141
  if (replace) {
25998
- const rmSync5 = (await import("fs")).rmSync;
25999
- if (existsSync17(commandsDir)) {
26000
- rmSync5(commandsDir, { recursive: true, force: true });
26142
+ const rmSync4 = (await import("fs")).rmSync;
26143
+ if (existsSync15(commandsDir)) {
26144
+ rmSync4(commandsDir, { recursive: true, force: true });
26001
26145
  console.log(`[OrchestrationToolsServer] Cleared commands directory for ${targetNodeId}`);
26002
26146
  }
26003
26147
  }
26004
- if (!existsSync17(commandsDir)) {
26005
- mkdirSync15(commandsDir, { recursive: true });
26148
+ if (!existsSync15(commandsDir)) {
26149
+ mkdirSync13(commandsDir, { recursive: true });
26006
26150
  }
26007
26151
  if (commandPreset) {
26008
26152
  const presetCommands = getPresetCommands3(commandPreset);
@@ -26017,19 +26161,19 @@ ${content}`;
26017
26161
  addedCommands.push(...addCommands);
26018
26162
  }
26019
26163
  if (removeCommands && removeCommands.length > 0) {
26020
- const { unlinkSync: unlinkSync11 } = await import("fs");
26164
+ const { unlinkSync: unlinkSync12 } = await import("fs");
26021
26165
  for (const cmdPath of removeCommands) {
26022
26166
  const parts = cmdPath.split(":");
26023
26167
  let targetPath;
26024
26168
  if (parts.length === 3) {
26025
- targetPath = join17(commandsDir, parts[0], parts[1], `${parts[2]}.md`);
26169
+ targetPath = join16(commandsDir, parts[0], parts[1], `${parts[2]}.md`);
26026
26170
  } else if (parts.length === 2) {
26027
- targetPath = join17(commandsDir, parts[0], `${parts[1]}.md`);
26171
+ targetPath = join16(commandsDir, parts[0], `${parts[1]}.md`);
26028
26172
  } else {
26029
26173
  continue;
26030
26174
  }
26031
- if (existsSync17(targetPath)) {
26032
- unlinkSync11(targetPath);
26175
+ if (existsSync15(targetPath)) {
26176
+ unlinkSync12(targetPath);
26033
26177
  removedCommands.push(cmdPath);
26034
26178
  console.log(`[OrchestrationToolsServer] Removed command ${cmdPath} from ${targetNodeId}`);
26035
26179
  }
@@ -28030,16 +28174,16 @@ var WORKSPACE_TASK_TOOLS = [
28030
28174
 
28031
28175
  // src/mcp/workspace-task-tools-server.ts
28032
28176
  import http3 from "http";
28033
- import { join as join19 } from "path";
28177
+ import { join as join18 } from "path";
28034
28178
 
28035
28179
  // src/services/artifact-service.ts
28036
- import { existsSync as existsSync18, mkdirSync as mkdirSync16, writeFileSync as writeFileSync15, readFileSync as readFileSync15, renameSync, unlinkSync as unlinkSync6, readdirSync as readdirSync8 } from "fs";
28037
- import { join as join18, dirname as dirname7 } from "path";
28038
- import { createHash as createHash2, randomUUID as randomUUID9 } from "crypto";
28180
+ import { existsSync as existsSync16, mkdirSync as mkdirSync14, writeFileSync as writeFileSync14, readFileSync as readFileSync13, renameSync, unlinkSync as unlinkSync6, readdirSync as readdirSync7 } from "fs";
28181
+ import { join as join17, dirname as dirname6 } from "path";
28182
+ import { createHash as createHash2, randomUUID as randomUUID8 } from "crypto";
28039
28183
  var ArtifactService = class {
28040
28184
  templatesDir;
28041
28185
  constructor(projectFolder) {
28042
- this.templatesDir = join18(projectFolder, ".viyv", "templates");
28186
+ this.templatesDir = join17(projectFolder, ".viyv", "templates");
28043
28187
  }
28044
28188
  /**
28045
28189
  * Create an artifact file with atomic write
@@ -28057,13 +28201,13 @@ var ArtifactService = class {
28057
28201
  agentName,
28058
28202
  projectFolder
28059
28203
  } = options;
28060
- const id = randomUUID9();
28204
+ const id = randomUUID8();
28061
28205
  const timestamp35 = /* @__PURE__ */ new Date();
28062
28206
  const dateStr = this.formatDateForFilename(timestamp35);
28063
28207
  const shortId = id.slice(0, 6);
28064
28208
  const slug = this.slugify(title);
28065
28209
  const filename = `${dateStr}-${shortId}-${slug}.md`;
28066
- const categoryDir = join18(projectFolder, ".viyv", "artifacts", category);
28210
+ const categoryDir = join17(projectFolder, ".viyv", "artifacts", category);
28067
28211
  this.ensureDir(categoryDir);
28068
28212
  let body;
28069
28213
  if (templateId) {
@@ -28091,11 +28235,11 @@ var ArtifactService = class {
28091
28235
  status
28092
28236
  };
28093
28237
  const fileContent = this.buildFileContent(frontmatter, body);
28094
- const absolutePath = join18(categoryDir, filename);
28238
+ const absolutePath = join17(categoryDir, filename);
28095
28239
  this.writeAtomic(absolutePath, fileContent);
28096
28240
  const fileSize = Buffer.byteLength(fileContent, "utf-8");
28097
28241
  const contentHash = this.hashContent(fileContent);
28098
- const filePath = join18(".viyv", "artifacts", category, filename);
28242
+ const filePath = join17(".viyv", "artifacts", category, filename);
28099
28243
  return {
28100
28244
  id,
28101
28245
  filePath,
@@ -28115,12 +28259,12 @@ var ArtifactService = class {
28115
28259
  templates.push(template);
28116
28260
  }
28117
28261
  }
28118
- if (existsSync18(this.templatesDir)) {
28262
+ if (existsSync16(this.templatesDir)) {
28119
28263
  try {
28120
- const files = readdirSync8(this.templatesDir);
28264
+ const files = readdirSync7(this.templatesDir);
28121
28265
  for (const file of files) {
28122
28266
  if (file.endsWith(".md")) {
28123
- const filePath = join18(this.templatesDir, file);
28267
+ const filePath = join17(this.templatesDir, file);
28124
28268
  const template = this.parseTemplateFile(filePath);
28125
28269
  if (template && (!category || template.category === category)) {
28126
28270
  templates.push(template);
@@ -28140,9 +28284,9 @@ var ArtifactService = class {
28140
28284
  const builtinTemplates = this.getBuiltinTemplates();
28141
28285
  const builtin = builtinTemplates.find((t) => t.id === templateId);
28142
28286
  if (builtin) return builtin;
28143
- if (existsSync18(this.templatesDir)) {
28144
- const filePath = join18(this.templatesDir, `${templateId}.md`);
28145
- if (existsSync18(filePath)) {
28287
+ if (existsSync16(this.templatesDir)) {
28288
+ const filePath = join17(this.templatesDir, `${templateId}.md`);
28289
+ if (existsSync16(filePath)) {
28146
28290
  return this.parseTemplateFile(filePath);
28147
28291
  }
28148
28292
  }
@@ -28152,7 +28296,7 @@ var ArtifactService = class {
28152
28296
  * Delete an artifact file
28153
28297
  */
28154
28298
  deleteArtifactFile(absolutePath) {
28155
- if (existsSync18(absolutePath)) {
28299
+ if (existsSync16(absolutePath)) {
28156
28300
  unlinkSync6(absolutePath);
28157
28301
  }
28158
28302
  }
@@ -28160,10 +28304,10 @@ var ArtifactService = class {
28160
28304
  * Read artifact content
28161
28305
  */
28162
28306
  readArtifactContent(absolutePath) {
28163
- if (!existsSync18(absolutePath)) {
28307
+ if (!existsSync16(absolutePath)) {
28164
28308
  return null;
28165
28309
  }
28166
- return readFileSync15(absolutePath, "utf-8");
28310
+ return readFileSync13(absolutePath, "utf-8");
28167
28311
  }
28168
28312
  /**
28169
28313
  * Update artifact content (file content, not just metadata)
@@ -28172,12 +28316,12 @@ var ArtifactService = class {
28172
28316
  */
28173
28317
  updateArtifactContent(absolutePath, newContent, options) {
28174
28318
  let frontmatter;
28175
- if (existsSync18(absolutePath)) {
28176
- const existingContent = readFileSync15(absolutePath, "utf-8");
28319
+ if (existsSync16(absolutePath)) {
28320
+ const existingContent = readFileSync13(absolutePath, "utf-8");
28177
28321
  frontmatter = this.parseFrontmatter(existingContent);
28178
28322
  } else {
28179
28323
  frontmatter = {
28180
- id: options?.artifactId || randomUUID9(),
28324
+ id: options?.artifactId || randomUUID8(),
28181
28325
  title: options?.title || "Artifact",
28182
28326
  category: options?.category || "general",
28183
28327
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -28236,9 +28380,9 @@ var ArtifactService = class {
28236
28380
  getTemplateContent(templateId) {
28237
28381
  const builtin = this.getBuiltinTemplateContent(templateId);
28238
28382
  if (builtin) return builtin;
28239
- const filePath = join18(this.templatesDir, `${templateId}.md`);
28240
- if (existsSync18(filePath)) {
28241
- const content = readFileSync15(filePath, "utf-8");
28383
+ const filePath = join17(this.templatesDir, `${templateId}.md`);
28384
+ if (existsSync16(filePath)) {
28385
+ const content = readFileSync13(filePath, "utf-8");
28242
28386
  return this.removeTemplateFrontmatter(content);
28243
28387
  }
28244
28388
  return null;
@@ -28248,7 +28392,7 @@ var ArtifactService = class {
28248
28392
  */
28249
28393
  parseTemplateFile(filePath) {
28250
28394
  try {
28251
- const content = readFileSync15(filePath, "utf-8");
28395
+ const content = readFileSync13(filePath, "utf-8");
28252
28396
  const frontmatter = this.parseFrontmatter(content);
28253
28397
  if (!frontmatter.id || !frontmatter.name) {
28254
28398
  return null;
@@ -28343,17 +28487,17 @@ ${body}`;
28343
28487
  * Atomic write using temp file + rename
28344
28488
  */
28345
28489
  writeAtomic(filePath, content) {
28346
- const tempPath = `${filePath}.${randomUUID9()}.tmp`;
28347
- this.ensureDir(dirname7(filePath));
28348
- writeFileSync15(tempPath, content, "utf-8");
28490
+ const tempPath = `${filePath}.${randomUUID8()}.tmp`;
28491
+ this.ensureDir(dirname6(filePath));
28492
+ writeFileSync14(tempPath, content, "utf-8");
28349
28493
  renameSync(tempPath, filePath);
28350
28494
  }
28351
28495
  /**
28352
28496
  * Ensure directory exists
28353
28497
  */
28354
28498
  ensureDir(dir) {
28355
- if (!existsSync18(dir)) {
28356
- mkdirSync16(dir, { recursive: true });
28499
+ if (!existsSync16(dir)) {
28500
+ mkdirSync14(dir, { recursive: true });
28357
28501
  }
28358
28502
  }
28359
28503
  /**
@@ -30061,7 +30205,7 @@ var WorkspaceTaskToolsServer = class _WorkspaceTaskToolsServer {
30061
30205
  return { success: false, error: getResult.error || "Artifact not found" };
30062
30206
  }
30063
30207
  try {
30064
- const absolutePath = join19(projectFolder, getResult.artifact.filePath);
30208
+ const absolutePath = join18(projectFolder, getResult.artifact.filePath);
30065
30209
  this.artifactService.deleteArtifactFile(absolutePath);
30066
30210
  } catch (error) {
30067
30211
  console.error("[WorkspaceTaskToolsServer] Error deleting artifact file:", error);
@@ -30088,7 +30232,7 @@ var WorkspaceTaskToolsServer = class _WorkspaceTaskToolsServer {
30088
30232
  if (!getResult.success || !getResult.artifact) {
30089
30233
  return { success: false, error: getResult.error || "Artifact not found" };
30090
30234
  }
30091
- const absolutePath = join19(projectFolder, getResult.artifact.filePath);
30235
+ const absolutePath = join18(projectFolder, getResult.artifact.filePath);
30092
30236
  let updateResult;
30093
30237
  try {
30094
30238
  updateResult = this.artifactService.updateArtifactContent(
@@ -30914,6 +31058,9 @@ var WorkspaceTaskToolsServer = class _WorkspaceTaskToolsServer {
30914
31058
  }
30915
31059
  };
30916
31060
 
31061
+ // src/mcp/index.ts
31062
+ init_browser_mcp_process();
31063
+
30917
31064
  // src/services/proxy/hub-request-client.ts
30918
31065
  var HubRequestClient = class {
30919
31066
  cloudBridge;
@@ -34708,39 +34855,45 @@ Messages starting with \`/\` should be executed immediately using the Skill tool
34708
34855
  7. **Agent creation is YOUR responsibility** - Execute /sys:agent:agent-create-plan directly
34709
34856
  8. **If plan requests agent creation** - Execute agent creation yourself
34710
34857
  `;
34711
- var DEFAULT_MCP_SERVERS = {
34712
- "chrome-devtools": {
34713
- type: "stdio",
34714
- command: "npx",
34715
- args: ["chrome-devtools-mcp@latest"]
34716
- }
34717
- };
34718
- var DEFAULT_CHROME_DEVTOOLS_TOOLS = [
34719
- // Input automation
34720
- "mcp__chrome-devtools__click",
34721
- "mcp__chrome-devtools__drag",
34722
- "mcp__chrome-devtools__fill",
34723
- "mcp__chrome-devtools__fill_form",
34724
- "mcp__chrome-devtools__handle_dialog",
34725
- "mcp__chrome-devtools__hover",
34726
- "mcp__chrome-devtools__upload_file",
34727
- "mcp__chrome-devtools__press_key",
34728
- // Navigation
34729
- "mcp__chrome-devtools__navigate_page",
34730
- "mcp__chrome-devtools__new_page",
34731
- "mcp__chrome-devtools__list_pages",
34732
- "mcp__chrome-devtools__select_page",
34733
- "mcp__chrome-devtools__close_page",
34734
- "mcp__chrome-devtools__navigate_page_history",
34735
- "mcp__chrome-devtools__wait_for",
34736
- // Debugging
34737
- "mcp__chrome-devtools__evaluate_script",
34738
- "mcp__chrome-devtools__list_console_messages",
34739
- "mcp__chrome-devtools__take_screenshot",
34740
- "mcp__chrome-devtools__take_snapshot",
34741
- // Network
34742
- "mcp__chrome-devtools__list_network_requests",
34743
- "mcp__chrome-devtools__get_network_request"
34858
+ var DEFAULT_MCP_SERVERS = {};
34859
+ var DEFAULT_BROWSER_TOOLS = [
34860
+ // Core Browser
34861
+ "mcp__viyv-browser__navigate",
34862
+ "mcp__viyv-browser__screenshot",
34863
+ "mcp__viyv-browser__click",
34864
+ "mcp__viyv-browser__type",
34865
+ "mcp__viyv-browser__key",
34866
+ "mcp__viyv-browser__scroll",
34867
+ "mcp__viyv-browser__hover",
34868
+ "mcp__viyv-browser__drag",
34869
+ "mcp__viyv-browser__read_page",
34870
+ "mcp__viyv-browser__find",
34871
+ "mcp__viyv-browser__form_input",
34872
+ "mcp__viyv-browser__javascript_exec",
34873
+ "mcp__viyv-browser__wait_for",
34874
+ "mcp__viyv-browser__get_page_text",
34875
+ "mcp__viyv-browser__handle_dialog",
34876
+ // Tab Management
34877
+ "mcp__viyv-browser__tabs_context",
34878
+ "mcp__viyv-browser__tabs_create",
34879
+ "mcp__viyv-browser__tab_close",
34880
+ "mcp__viyv-browser__select_tab",
34881
+ // Debug
34882
+ "mcp__viyv-browser__read_console_messages",
34883
+ "mcp__viyv-browser__read_network_requests",
34884
+ // Advanced
34885
+ "mcp__viyv-browser__gif_creator",
34886
+ "mcp__viyv-browser__upload_image",
34887
+ "mcp__viyv-browser__update_plan",
34888
+ "mcp__viyv-browser__resize_window",
34889
+ // Agent Integration
34890
+ "mcp__viyv-browser__agent_tab_assign",
34891
+ "mcp__viyv-browser__agent_tab_list",
34892
+ "mcp__viyv-browser__browser_event_subscribe",
34893
+ "mcp__viyv-browser__browser_event_unsubscribe",
34894
+ "mcp__viyv-browser__artifact_from_page",
34895
+ "mcp__viyv-browser__page_data_extract",
34896
+ "mcp__viyv-browser__browser_health"
34744
34897
  ];
34745
34898
  var WORKSPACE_TASK_TOOLS2 = [
34746
34899
  // Task CRUD
@@ -34837,8 +34990,8 @@ var ORCHESTRATOR_CONFIG = {
34837
34990
  // Allow editing files (for command updates)
34838
34991
  "Bash",
34839
34992
  // Allow shell commands (for command deletion)
34840
- // ★ Chrome DevTools MCP browser automation tools (via CDP)
34841
- ...DEFAULT_CHROME_DEVTOOLS_TOOLS,
34993
+ // ★ Browser automation tools (viyv-browser MCP)
34994
+ ...DEFAULT_BROWSER_TOOLS,
34842
34995
  // ★ Workspace Task Tools (for autonomous task management)
34843
34996
  ...WORKSPACE_TASK_TOOLS2
34844
34997
  ],
@@ -35129,13 +35282,7 @@ mcp__workspace-task-tools__ws_artifact_update_content({
35129
35282
  4. **Handle errors** - Report issues promptly with context
35130
35283
  5. **Stay focused** - Complete the requested task efficiently
35131
35284
  `;
35132
- var STANDALONE_MCP_SERVERS = {
35133
- "chrome-devtools": {
35134
- type: "stdio",
35135
- command: "npx",
35136
- args: ["chrome-devtools-mcp@latest"]
35137
- }
35138
- };
35285
+ var STANDALONE_MCP_SERVERS = {};
35139
35286
  var WORKSPACE_TASK_TOOLS3 = [
35140
35287
  // Task CRUD
35141
35288
  "mcp__workspace-task-tools__ws_task_create",
@@ -35206,8 +35353,8 @@ var STANDALONE_AGENT_CONFIG = {
35206
35353
  // Slash commands and skills
35207
35354
  "SlashCommand",
35208
35355
  "Skill",
35209
- // Chrome DevTools MCP browser automation
35210
- ...DEFAULT_CHROME_DEVTOOLS_TOOLS,
35356
+ // Browser automation tools (viyv-browser MCP)
35357
+ ...DEFAULT_BROWSER_TOOLS,
35211
35358
  // Workspace Task Tools
35212
35359
  ...WORKSPACE_TASK_TOOLS3
35213
35360
  ],
@@ -35278,7 +35425,7 @@ async function disposeRuntime() {
35278
35425
  }
35279
35426
 
35280
35427
  // src/orchestrator/context-builder.ts
35281
- import { existsSync as existsSync19, readdirSync as readdirSync9, readFileSync as readFileSync16 } from "fs";
35428
+ import { existsSync as existsSync18, readdirSync as readdirSync8, readFileSync as readFileSync15 } from "fs";
35282
35429
  import { join as join20 } from "path";
35283
35430
  function buildChildAgentContext(processes) {
35284
35431
  return processes.map((proc) => ({
@@ -35363,13 +35510,13 @@ function buildOrchestratorPrompt(basePrompt, processes, projectSettings) {
35363
35510
  }
35364
35511
  function scanCommandsForPrompt(commandsDir) {
35365
35512
  const commands = [];
35366
- if (!existsSync19(commandsDir)) {
35513
+ if (!existsSync18(commandsDir)) {
35367
35514
  return commands;
35368
35515
  }
35369
35516
  const categories = ["user", "sys", "tpl"];
35370
35517
  for (const category of categories) {
35371
35518
  const categoryDir = join20(commandsDir, category);
35372
- if (existsSync19(categoryDir)) {
35519
+ if (existsSync18(categoryDir)) {
35373
35520
  scanCommandsDirRecursive2(categoryDir, category, commands, commandsDir);
35374
35521
  }
35375
35522
  }
@@ -35377,7 +35524,7 @@ function scanCommandsForPrompt(commandsDir) {
35377
35524
  }
35378
35525
  function scanCommandsDirRecursive2(dir, prefix, commands, baseDir) {
35379
35526
  try {
35380
- const entries = readdirSync9(dir, { withFileTypes: true });
35527
+ const entries = readdirSync8(dir, { withFileTypes: true });
35381
35528
  for (const entry of entries) {
35382
35529
  const fullPath = join20(dir, entry.name);
35383
35530
  if (entry.isDirectory()) {
@@ -35388,7 +35535,7 @@ function scanCommandsDirRecursive2(dir, prefix, commands, baseDir) {
35388
35535
  const id = `${prefix}:${baseName}`;
35389
35536
  const filePath = fullPath.replace(baseDir, ".claude/commands").replace(/^\//, "");
35390
35537
  try {
35391
- const content = readFileSync16(fullPath, "utf-8");
35538
+ const content = readFileSync15(fullPath, "utf-8");
35392
35539
  const metadata = extractMinimalMetadata(content);
35393
35540
  commands.push({
35394
35541
  id,
@@ -35803,7 +35950,7 @@ function getPreset(type) {
35803
35950
  init_daemon_configs();
35804
35951
 
35805
35952
  // src/managers/command-discovery-manager.ts
35806
- import { existsSync as existsSync20, readdirSync as readdirSync10, readFileSync as readFileSync17 } from "fs";
35953
+ import { existsSync as existsSync20, readdirSync as readdirSync9, readFileSync as readFileSync17 } from "fs";
35807
35954
  import { join as join21 } from "path";
35808
35955
  var CommandDiscoveryManager = class {
35809
35956
  /**
@@ -35875,7 +36022,7 @@ var CommandDiscoveryManager = class {
35875
36022
  scanCommandsDir(dir, prefix, commands, baseCwd) {
35876
36023
  if (!existsSync20(dir)) return;
35877
36024
  try {
35878
- const entries = readdirSync10(dir, { withFileTypes: true });
36025
+ const entries = readdirSync9(dir, { withFileTypes: true });
35879
36026
  for (const entry of entries) {
35880
36027
  const fullPath = join21(dir, entry.name);
35881
36028
  if (entry.isDirectory()) {
@@ -36050,7 +36197,7 @@ var CommandDiscoveryManager = class {
36050
36197
 
36051
36198
  // src/managers/command-setup-manager.ts
36052
36199
  init_command_templates();
36053
- import { existsSync as existsSync21, mkdirSync as mkdirSync17, writeFileSync as writeFileSync16, readdirSync as readdirSync11, rmSync as rmSync3, renameSync as renameSync2 } from "fs";
36200
+ import { existsSync as existsSync21, mkdirSync as mkdirSync16, writeFileSync as writeFileSync17, readdirSync as readdirSync10, rmSync as rmSync2, renameSync as renameSync2 } from "fs";
36054
36201
  import { join as join22 } from "path";
36055
36202
  var CommandSetupManager = class {
36056
36203
  /**
@@ -36060,23 +36207,23 @@ var CommandSetupManager = class {
36060
36207
  writeSharedReferencesAndSkills(baseDir) {
36061
36208
  const referencesDir = join22(baseDir, ".claude", "references");
36062
36209
  if (!existsSync21(referencesDir)) {
36063
- mkdirSync17(referencesDir, { recursive: true });
36210
+ mkdirSync16(referencesDir, { recursive: true });
36064
36211
  }
36065
36212
  for (const ref of SHARED_REFERENCES) {
36066
36213
  const refPath = join22(referencesDir, `${ref.filename}.md`);
36067
- writeFileSync16(refPath, ref.content, "utf-8");
36214
+ writeFileSync17(refPath, ref.content, "utf-8");
36068
36215
  }
36069
36216
  const skillsDir = join22(baseDir, ".claude", "skills");
36070
36217
  if (!existsSync21(skillsDir)) {
36071
- mkdirSync17(skillsDir, { recursive: true });
36218
+ mkdirSync16(skillsDir, { recursive: true });
36072
36219
  }
36073
36220
  for (const skill of SHARED_SKILLS) {
36074
36221
  const skillDir = join22(skillsDir, skill.name);
36075
36222
  if (!existsSync21(skillDir)) {
36076
- mkdirSync17(skillDir, { recursive: true });
36223
+ mkdirSync16(skillDir, { recursive: true });
36077
36224
  }
36078
36225
  const skillPath = join22(skillDir, "SKILL.md");
36079
- writeFileSync16(skillPath, skill.content, "utf-8");
36226
+ writeFileSync17(skillPath, skill.content, "utf-8");
36080
36227
  }
36081
36228
  }
36082
36229
  /**
@@ -36089,7 +36236,7 @@ var CommandSetupManager = class {
36089
36236
  const dirPath = join22(commandsDir, dir);
36090
36237
  if (existsSync21(dirPath)) {
36091
36238
  try {
36092
- rmSync3(dirPath, { recursive: true, force: true });
36239
+ rmSync2(dirPath, { recursive: true, force: true });
36093
36240
  } catch (error) {
36094
36241
  if (error.code !== "ENOTEMPTY") {
36095
36242
  throw error;
@@ -36104,7 +36251,7 @@ var CommandSetupManager = class {
36104
36251
  */
36105
36252
  writeCommands(commandsDir, commands, clearFirst = false) {
36106
36253
  if (!existsSync21(commandsDir)) {
36107
- mkdirSync17(commandsDir, { recursive: true });
36254
+ mkdirSync16(commandsDir, { recursive: true });
36108
36255
  }
36109
36256
  if (clearFirst) {
36110
36257
  this.clearManagedCommands(commandsDir);
@@ -36112,13 +36259,13 @@ var CommandSetupManager = class {
36112
36259
  for (const [name, definition] of Object.entries(commands)) {
36113
36260
  const targetDir = definition.namespace ? join22(commandsDir, definition.namespace) : commandsDir;
36114
36261
  if (definition.namespace && !existsSync21(targetDir)) {
36115
- mkdirSync17(targetDir, { recursive: true });
36262
+ mkdirSync16(targetDir, { recursive: true });
36116
36263
  }
36117
36264
  const mdFilePath = join22(targetDir, `${name}.md`);
36118
- writeFileSync16(mdFilePath, definition.content, "utf-8");
36265
+ writeFileSync17(mdFilePath, definition.content, "utf-8");
36119
36266
  if (definition.metadata) {
36120
36267
  const metaFilePath = join22(targetDir, `${name}.meta.json`);
36121
- writeFileSync16(metaFilePath, JSON.stringify(definition.metadata, null, 2), "utf-8");
36268
+ writeFileSync17(metaFilePath, JSON.stringify(definition.metadata, null, 2), "utf-8");
36122
36269
  }
36123
36270
  }
36124
36271
  }
@@ -36139,7 +36286,7 @@ var CommandSetupManager = class {
36139
36286
  const newPath = join22(sysDir, ns);
36140
36287
  if (existsSync21(oldPath)) {
36141
36288
  if (!existsSync21(sysDir)) {
36142
- mkdirSync17(sysDir, { recursive: true });
36289
+ mkdirSync16(sysDir, { recursive: true });
36143
36290
  }
36144
36291
  renameSync2(oldPath, newPath);
36145
36292
  migratedCount++;
@@ -36161,7 +36308,7 @@ var CommandSetupManager = class {
36161
36308
  const dirPath = join22(commandsDir, dir);
36162
36309
  if (existsSync21(dirPath)) {
36163
36310
  try {
36164
- rmSync3(dirPath, { recursive: true, force: true });
36311
+ rmSync2(dirPath, { recursive: true, force: true });
36165
36312
  console.log(`[CommandSetupManager] Removed standalone-only directory: ${dir}`);
36166
36313
  } catch (error) {
36167
36314
  if (error.code !== "ENOTEMPTY") {
@@ -36196,7 +36343,7 @@ var CommandSetupManager = class {
36196
36343
  const dirPath = join22(commandsDir, dir);
36197
36344
  if (existsSync21(dirPath)) {
36198
36345
  try {
36199
- rmSync3(dirPath, { recursive: true, force: true });
36346
+ rmSync2(dirPath, { recursive: true, force: true });
36200
36347
  console.log(`[CommandSetupManager] Removed orchestrator-only directory: ${dir}`);
36201
36348
  } catch (error) {
36202
36349
  if (error.code !== "ENOTEMPTY") {
@@ -36217,7 +36364,7 @@ var CommandSetupManager = class {
36217
36364
  const filePath = join22(commandsDir, file);
36218
36365
  if (existsSync21(filePath)) {
36219
36366
  try {
36220
- rmSync3(filePath, { force: true });
36367
+ rmSync2(filePath, { force: true });
36221
36368
  console.log(`[CommandSetupManager] Removed orchestrator-only file: ${file}`);
36222
36369
  } catch {
36223
36370
  }
@@ -36227,7 +36374,7 @@ var CommandSetupManager = class {
36227
36374
  const sysDir = join22(commandsDir, "sys");
36228
36375
  if (existsSync21(sysDir)) {
36229
36376
  try {
36230
- rmSync3(sysDir, { recursive: true, force: true });
36377
+ rmSync2(sysDir, { recursive: true, force: true });
36231
36378
  } catch (error) {
36232
36379
  if (error.code !== "ENOTEMPTY") {
36233
36380
  throw error;
@@ -36263,7 +36410,7 @@ var CommandSetupManager = class {
36263
36410
  const sysDir = join22(commandsDir, "sys");
36264
36411
  if (existsSync21(sysDir)) {
36265
36412
  try {
36266
- rmSync3(sysDir, { recursive: true, force: true });
36413
+ rmSync2(sysDir, { recursive: true, force: true });
36267
36414
  } catch (error) {
36268
36415
  if (error.code !== "ENOTEMPTY") {
36269
36416
  throw error;
@@ -36285,7 +36432,7 @@ var CommandSetupManager = class {
36285
36432
  return;
36286
36433
  }
36287
36434
  try {
36288
- const entries = readdirSync11(workspacesDir, { withFileTypes: true });
36435
+ const entries = readdirSync10(workspacesDir, { withFileTypes: true });
36289
36436
  const workspaces2 = entries.filter((e) => e.isDirectory()).map((e) => e.name);
36290
36437
  for (const workspaceId of workspaces2) {
36291
36438
  const workspaceDir = join22(workspacesDir, workspaceId);
@@ -36324,7 +36471,7 @@ var CommandSetupManager = class {
36324
36471
  return;
36325
36472
  }
36326
36473
  try {
36327
- const entries = readdirSync11(systemAgentsDir, { withFileTypes: true });
36474
+ const entries = readdirSync10(systemAgentsDir, { withFileTypes: true });
36328
36475
  const workspaces2 = entries.filter((e) => e.isDirectory()).map((e) => e.name);
36329
36476
  for (const workspaceId of workspaces2) {
36330
36477
  const workspaceDir = join22(systemAgentsDir, workspaceId);
@@ -36338,7 +36485,7 @@ var CommandSetupManager = class {
36338
36485
  };
36339
36486
 
36340
36487
  // src/managers/process-manager.ts
36341
- import { existsSync as existsSync22, mkdirSync as mkdirSync18, writeFileSync as writeFileSync17 } from "fs";
36488
+ import { existsSync as existsSync22, mkdirSync as mkdirSync17, writeFileSync as writeFileSync18 } from "fs";
36342
36489
  import { join as join23 } from "path";
36343
36490
  import { randomUUID as randomUUID10 } from "crypto";
36344
36491
  var ProcessManager = class {
@@ -36382,13 +36529,13 @@ var ProcessManager = class {
36382
36529
  if (workingDirectory) {
36383
36530
  effectiveWorkingDirectory = workingDirectory;
36384
36531
  if (!existsSync22(effectiveWorkingDirectory)) {
36385
- mkdirSync18(effectiveWorkingDirectory, { recursive: true });
36532
+ mkdirSync17(effectiveWorkingDirectory, { recursive: true });
36386
36533
  console.log(`[ProcessManager] Created workspace directory: ${effectiveWorkingDirectory}`);
36387
36534
  }
36388
36535
  } else {
36389
36536
  const nodeWorkDir = `${workspacesBaseDir}/${childNodeId}`;
36390
36537
  if (!existsSync22(nodeWorkDir)) {
36391
- mkdirSync18(nodeWorkDir, { recursive: true });
36538
+ mkdirSync17(nodeWorkDir, { recursive: true });
36392
36539
  console.log(`[ProcessManager] Created workspace directory: ${nodeWorkDir}`);
36393
36540
  }
36394
36541
  effectiveWorkingDirectory = nodeWorkDir;
@@ -36403,7 +36550,7 @@ var ProcessManager = class {
36403
36550
  try {
36404
36551
  const mcpConfigPath = join23(effectiveWorkingDirectory, ".mcp.json");
36405
36552
  const mcpConfig = { mcpServers };
36406
- writeFileSync17(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
36553
+ writeFileSync18(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
36407
36554
  console.log(`[ProcessManager] Wrote MCP config to ${mcpConfigPath} with ${Object.keys(mcpServers).length} servers`);
36408
36555
  } catch (error) {
36409
36556
  console.warn(`[ProcessManager] Failed to write MCP config:`, error);
@@ -36617,7 +36764,7 @@ var ProcessManager = class {
36617
36764
  };
36618
36765
 
36619
36766
  // src/managers/orchestration-manager.ts
36620
- import { existsSync as existsSync23, writeFileSync as writeFileSync18, readFileSync as readFileSync18 } from "fs";
36767
+ import { existsSync as existsSync23, writeFileSync as writeFileSync19, readFileSync as readFileSync18 } from "fs";
36621
36768
  import { join as join24 } from "path";
36622
36769
  import { randomUUID as randomUUID11 } from "crypto";
36623
36770
  init_dist();
@@ -36642,8 +36789,9 @@ var OrchestrationManager = class {
36642
36789
  * Called by daemon.updateCommands() to refresh MCP config
36643
36790
  * @param workspaceTaskToolsUrl Optional URL for workspace-task-tools MCP server
36644
36791
  * @param googleMcpUrl Optional URL for Google MCP server (viyv-google)
36792
+ * @param browserMcpUrl Optional URL for Browser MCP server (viyv-browser)
36645
36793
  */
36646
- updateMcpConfig(workspaceTaskToolsUrl, googleMcpUrl) {
36794
+ updateMcpConfig(workspaceTaskToolsUrl, googleMcpUrl, browserMcpUrl) {
36647
36795
  const daemonState = this.deps.getDaemonState();
36648
36796
  const mcpConfigPath = `${daemonState.projectDir}/.mcp.json`;
36649
36797
  let existingMcpServers = {};
@@ -36667,9 +36815,16 @@ var OrchestrationManager = class {
36667
36815
  url: `${googleMcpUrl}/sse`
36668
36816
  };
36669
36817
  }
36818
+ if (browserMcpUrl) {
36819
+ dynamicMcpServers["viyv-browser"] = {
36820
+ type: "sse",
36821
+ url: `${browserMcpUrl}/sse`
36822
+ };
36823
+ }
36670
36824
  let mcpConfig;
36671
36825
  if (this.mode === "agent") {
36672
36826
  delete existingMcpServers["orchestration-tools"];
36827
+ delete existingMcpServers["chrome-devtools"];
36673
36828
  const configMcpServers = STANDALONE_MCP_SERVERS;
36674
36829
  mcpConfig = {
36675
36830
  mcpServers: {
@@ -36679,6 +36834,7 @@ var OrchestrationManager = class {
36679
36834
  }
36680
36835
  };
36681
36836
  } else {
36837
+ delete existingMcpServers["chrome-devtools"];
36682
36838
  const configMcpServers = ORCHESTRATOR_CONFIG.mcpServers || {};
36683
36839
  mcpConfig = {
36684
36840
  mcpServers: {
@@ -36694,15 +36850,16 @@ var OrchestrationManager = class {
36694
36850
  }
36695
36851
  };
36696
36852
  }
36697
- writeFileSync18(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
36853
+ writeFileSync19(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
36698
36854
  console.log(`[OrchestrationManager] Updated MCP config at ${mcpConfigPath} with ${Object.keys(mcpConfig.mcpServers).length} servers (${this.mode} mode)`);
36699
36855
  }
36700
36856
  /**
36701
36857
  * Start the orchestration/standalone server based on daemon mode
36702
36858
  * @param workspaceTaskToolsUrl Optional URL for workspace-task-tools MCP server
36703
36859
  * @param mode Daemon mode: 'agent' (standalone) or 'team' (orchestrator + children)
36860
+ * @param browserMcpUrl Optional URL for Browser MCP server (viyv-browser)
36704
36861
  */
36705
- async startOrchestrationServer(workspaceTaskToolsUrl, mode = "team") {
36862
+ async startOrchestrationServer(workspaceTaskToolsUrl, mode = "team", browserMcpUrl) {
36706
36863
  if (this.mode === "team" && mode === "agent" && this.orchestrationServer) {
36707
36864
  console.log(`[OrchestrationManager] Mode transition: team \u2192 agent, stopping orchestration server`);
36708
36865
  try {
@@ -36715,7 +36872,7 @@ var OrchestrationManager = class {
36715
36872
  this.mode = mode;
36716
36873
  if (mode === "agent") {
36717
36874
  console.log(`[OrchestrationManager] Starting in Agent mode (standalone)`);
36718
- await this.startStandaloneProcess(workspaceTaskToolsUrl);
36875
+ await this.startStandaloneProcess(workspaceTaskToolsUrl, browserMcpUrl);
36719
36876
  return;
36720
36877
  }
36721
36878
  console.log(`[OrchestrationManager] Starting in Team mode (orchestrator + children)`);
@@ -36735,26 +36892,33 @@ var OrchestrationManager = class {
36735
36892
  console.warn("[OrchestrationManager] Failed to parse existing .mcp.json, starting fresh");
36736
36893
  }
36737
36894
  }
36738
- const workspaceTaskToolsMcp = {};
36895
+ delete existingMcpServers["chrome-devtools"];
36896
+ const dynamicMcpServers = {};
36739
36897
  if (workspaceTaskToolsUrl) {
36740
- workspaceTaskToolsMcp["workspace-task-tools"] = {
36898
+ dynamicMcpServers["workspace-task-tools"] = {
36741
36899
  type: "http",
36742
36900
  url: workspaceTaskToolsUrl
36743
36901
  };
36744
36902
  }
36903
+ if (browserMcpUrl) {
36904
+ dynamicMcpServers["viyv-browser"] = {
36905
+ type: "sse",
36906
+ url: `${browserMcpUrl}/sse`
36907
+ };
36908
+ }
36745
36909
  const configMcpServers = ORCHESTRATOR_CONFIG.mcpServers || {};
36746
36910
  const mcpConfig = {
36747
36911
  mcpServers: {
36748
36912
  ...existingMcpServers,
36749
36913
  ...configMcpServers,
36750
- ...workspaceTaskToolsMcp,
36914
+ ...dynamicMcpServers,
36751
36915
  "orchestration-tools": {
36752
36916
  type: "http",
36753
36917
  url: this.orchestrationServer.getUrl()
36754
36918
  }
36755
36919
  }
36756
36920
  };
36757
- writeFileSync18(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
36921
+ writeFileSync19(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
36758
36922
  console.log(`[OrchestrationManager] Updated MCP config at ${mcpConfigPath} with ${Object.keys(mcpConfig.mcpServers).length} servers`);
36759
36923
  await this.startOrchestratorProcess();
36760
36924
  } catch (error) {
@@ -36765,7 +36929,7 @@ var OrchestrationManager = class {
36765
36929
  * Start a standalone agent process (agent mode - no orchestration)
36766
36930
  * @param workspaceTaskToolsUrl Optional URL for workspace-task-tools MCP server
36767
36931
  */
36768
- async startStandaloneProcess(workspaceTaskToolsUrl) {
36932
+ async startStandaloneProcess(workspaceTaskToolsUrl, browserMcpUrl) {
36769
36933
  try {
36770
36934
  const daemonState = this.deps.getDaemonState();
36771
36935
  const processId = randomUUID11();
@@ -36782,22 +36946,29 @@ var OrchestrationManager = class {
36782
36946
  console.warn("[OrchestrationManager] Failed to parse existing .mcp.json, starting fresh");
36783
36947
  }
36784
36948
  }
36785
- const workspaceTaskToolsMcp = {};
36949
+ delete existingMcpServers["chrome-devtools"];
36950
+ const dynamicMcpServers = {};
36786
36951
  if (workspaceTaskToolsUrl) {
36787
- workspaceTaskToolsMcp["workspace-task-tools"] = {
36952
+ dynamicMcpServers["workspace-task-tools"] = {
36788
36953
  type: "http",
36789
36954
  url: workspaceTaskToolsUrl
36790
36955
  };
36791
36956
  }
36957
+ if (browserMcpUrl) {
36958
+ dynamicMcpServers["viyv-browser"] = {
36959
+ type: "sse",
36960
+ url: `${browserMcpUrl}/sse`
36961
+ };
36962
+ }
36792
36963
  const configMcpServers = STANDALONE_MCP_SERVERS;
36793
36964
  const mcpConfig = {
36794
36965
  mcpServers: {
36795
36966
  ...existingMcpServers,
36796
36967
  ...configMcpServers,
36797
- ...workspaceTaskToolsMcp
36968
+ ...dynamicMcpServers
36798
36969
  }
36799
36970
  };
36800
- writeFileSync18(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
36971
+ writeFileSync19(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
36801
36972
  console.log(`[OrchestrationManager] Updated MCP config at ${mcpConfigPath} with ${Object.keys(mcpConfig.mcpServers).length} servers (standalone mode)`);
36802
36973
  const projectSettings = this.deps.getProjectSettings();
36803
36974
  let systemPrompt = STANDALONE_AGENT_SYSTEM_PROMPT;
@@ -37325,7 +37496,7 @@ ${personaPrompt}` : systemPromptWithTopology;
37325
37496
  };
37326
37497
 
37327
37498
  // src/managers/hub-sync-manager.ts
37328
- import { writeFileSync as writeFileSync19, mkdirSync as mkdirSync19, readFileSync as readFileSync19, existsSync as existsSync24 } from "fs";
37499
+ import { writeFileSync as writeFileSync20, mkdirSync as mkdirSync18, readFileSync as readFileSync19, existsSync as existsSync24 } from "fs";
37329
37500
  import { join as join25 } from "path";
37330
37501
  import { randomUUID as randomUUID12 } from "crypto";
37331
37502
  var HubSyncManager = class {
@@ -37423,8 +37594,8 @@ var HubSyncManager = class {
37423
37594
  }
37424
37595
  try {
37425
37596
  const dir = join25(filePath, "..");
37426
- mkdirSync19(dir, { recursive: true });
37427
- writeFileSync19(filePath, JSON.stringify(this.projectSettings, null, 2), "utf-8");
37597
+ mkdirSync18(dir, { recursive: true });
37598
+ writeFileSync20(filePath, JSON.stringify(this.projectSettings, null, 2), "utf-8");
37428
37599
  } catch (error) {
37429
37600
  console.error(`[HubSyncManager] Failed to write project settings file:`, error);
37430
37601
  }
@@ -37482,10 +37653,10 @@ var HubSyncManager = class {
37482
37653
 
37483
37654
  // src/managers/agent-node-manager.ts
37484
37655
  init_dist();
37485
- import { existsSync as existsSync25, readdirSync as readdirSync12, readFileSync as readFileSync20, writeFileSync as writeFileSync20, rmSync as rmSync4, mkdirSync as mkdirSync20 } from "fs";
37656
+ import { existsSync as existsSync25, readdirSync as readdirSync11, readFileSync as readFileSync20, writeFileSync as writeFileSync21, rmSync as rmSync3, mkdirSync as mkdirSync19 } from "fs";
37486
37657
  import { join as join26 } from "path";
37487
37658
  import { randomUUID as randomUUID13 } from "crypto";
37488
- import { homedir as homedir12 } from "os";
37659
+ import { homedir as homedir11 } from "os";
37489
37660
  import * as yaml4 from "yaml";
37490
37661
 
37491
37662
  // src/config/child-agent-common.ts
@@ -37859,7 +38030,7 @@ var AgentNodeManager = class {
37859
38030
  try {
37860
38031
  const mcpConfigPath = join26(nodeResult.cwd, ".mcp.json");
37861
38032
  const mcpConfig = { mcpServers };
37862
- writeFileSync20(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
38033
+ writeFileSync21(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
37863
38034
  console.log(`[AgentNodeManager] Wrote MCP config to ${mcpConfigPath} with ${Object.keys(mcpServers).length} servers`);
37864
38035
  } catch (error) {
37865
38036
  console.warn(`[AgentNodeManager] Failed to write MCP config:`, error);
@@ -37972,7 +38143,7 @@ ${personaPrompt}` : promptWithCommonInstructions;
37972
38143
  async applyCommandPresetToChild(childCwd, commandPreset, customCommands) {
37973
38144
  const commandsDir = join26(childCwd, ".claude", "commands");
37974
38145
  if (!existsSync25(commandsDir)) {
37975
- mkdirSync20(commandsDir, { recursive: true });
38146
+ mkdirSync19(commandsDir, { recursive: true });
37976
38147
  }
37977
38148
  if (commandPreset) {
37978
38149
  const { getPresetCommands: getPresetCommands3, hasCommandPreset: hasCommandPreset2, getAvailablePresets: getAvailablePresets2 } = await Promise.resolve().then(() => (init_command_presets(), command_presets_exports));
@@ -38128,11 +38299,11 @@ ${personaPrompt}` : promptWithCommonInstructions;
38128
38299
  * Also removes context and workspace directories for the agent
38129
38300
  */
38130
38301
  removeAgentFromTopologies(nodeId) {
38131
- const baseDir = join26(homedir12(), ".viyv-agent");
38302
+ const baseDir = join26(homedir11(), ".viyv-agent");
38132
38303
  const topologiesDir = join26(baseDir, "topologies");
38133
38304
  if (existsSync25(topologiesDir)) {
38134
38305
  try {
38135
- const projectDirs = readdirSync12(topologiesDir);
38306
+ const projectDirs = readdirSync11(topologiesDir);
38136
38307
  for (const projectId of projectDirs) {
38137
38308
  const topologyPath = join26(topologiesDir, projectId, "topology.yaml");
38138
38309
  if (!existsSync25(topologyPath)) continue;
@@ -38143,7 +38314,7 @@ ${personaPrompt}` : promptWithCommonInstructions;
38143
38314
  if (agentIndex !== void 0 && agentIndex >= 0) {
38144
38315
  topology.agents.splice(agentIndex, 1);
38145
38316
  topology.metadata.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
38146
- writeFileSync20(topologyPath, yaml4.stringify(topology), "utf-8");
38317
+ writeFileSync21(topologyPath, yaml4.stringify(topology), "utf-8");
38147
38318
  console.log(`[AgentNodeManager] Removed agent ${nodeId} from topology ${projectId}`);
38148
38319
  }
38149
38320
  } catch (err) {
@@ -38157,7 +38328,7 @@ ${personaPrompt}` : promptWithCommonInstructions;
38157
38328
  const contextDir = join26(baseDir, "contexts", nodeId);
38158
38329
  if (existsSync25(contextDir)) {
38159
38330
  try {
38160
- rmSync4(contextDir, { recursive: true, force: true });
38331
+ rmSync3(contextDir, { recursive: true, force: true });
38161
38332
  console.log(`[AgentNodeManager] Removed context directory for ${nodeId}`);
38162
38333
  } catch (err) {
38163
38334
  console.warn(`[AgentNodeManager] Failed to remove context directory:`, err);
@@ -38166,7 +38337,7 @@ ${personaPrompt}` : promptWithCommonInstructions;
38166
38337
  const workspaceDir = join26(baseDir, "workspaces", nodeId);
38167
38338
  if (existsSync25(workspaceDir)) {
38168
38339
  try {
38169
- rmSync4(workspaceDir, { recursive: true, force: true });
38340
+ rmSync3(workspaceDir, { recursive: true, force: true });
38170
38341
  console.log(`[AgentNodeManager] Removed workspace directory for ${nodeId}`);
38171
38342
  } catch (err) {
38172
38343
  console.warn(`[AgentNodeManager] Failed to remove workspace directory:`, err);
@@ -38175,7 +38346,7 @@ ${personaPrompt}` : promptWithCommonInstructions;
38175
38346
  const sessionDir = join26(baseDir, "sessions", nodeId);
38176
38347
  if (existsSync25(sessionDir)) {
38177
38348
  try {
38178
- rmSync4(sessionDir, { recursive: true, force: true });
38349
+ rmSync3(sessionDir, { recursive: true, force: true });
38179
38350
  console.log(`[AgentNodeManager] Removed session directory for ${nodeId}`);
38180
38351
  } catch (err) {
38181
38352
  console.warn(`[AgentNodeManager] Failed to remove session directory:`, err);
@@ -38894,7 +39065,7 @@ var IpcEventManager = class {
38894
39065
  };
38895
39066
 
38896
39067
  // src/managers/message-router-manager.ts
38897
- var PACKAGE_VERSION2 = "0.1.8";
39068
+ var PACKAGE_VERSION2 = "0.1.9";
38898
39069
  var MessageRouterManager = class {
38899
39070
  deps;
38900
39071
  constructor(deps) {
@@ -39189,7 +39360,7 @@ var MessageRouterManager = class {
39189
39360
 
39190
39361
  // src/managers/avatar-pool-manager.ts
39191
39362
  import { randomUUID as randomUUID16 } from "crypto";
39192
- import { existsSync as existsSync26, readFileSync as readFileSync21, writeFileSync as writeFileSync21, mkdirSync as mkdirSync21 } from "fs";
39363
+ import { existsSync as existsSync26, readFileSync as readFileSync21, writeFileSync as writeFileSync22, mkdirSync as mkdirSync20 } from "fs";
39193
39364
  import { join as join27, dirname as dirname8 } from "path";
39194
39365
  var AVATAR_COUNT = 14;
39195
39366
  var AVATAR_BASE_PATH = "/avatars/";
@@ -39360,9 +39531,9 @@ var AvatarPoolManager = class {
39360
39531
  const filePath = this.getOrchestratorAvatarPath();
39361
39532
  const dir = dirname8(filePath);
39362
39533
  if (!existsSync26(dir)) {
39363
- mkdirSync21(dir, { recursive: true });
39534
+ mkdirSync20(dir, { recursive: true });
39364
39535
  }
39365
- writeFileSync21(filePath, JSON.stringify({ avatarUrl, savedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
39536
+ writeFileSync22(filePath, JSON.stringify({ avatarUrl, savedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
39366
39537
  console.log(`[AvatarPoolManager] Saved orchestrator avatar to local storage: ${avatarUrl}`);
39367
39538
  } catch (err) {
39368
39539
  console.warn("[AvatarPoolManager] Failed to save orchestrator avatar to local storage:", err);
@@ -39820,7 +39991,7 @@ var IpcServer = class {
39820
39991
  };
39821
39992
 
39822
39993
  // ../../packages/node-sdk/dist/process-manager.js
39823
- import { spawn as spawn2 } from "child_process";
39994
+ import { spawn as spawn3 } from "child_process";
39824
39995
  import { randomUUID as randomUUID17 } from "crypto";
39825
39996
  import * as fs9 from "fs";
39826
39997
  import * as os2 from "os";
@@ -39899,7 +40070,7 @@ var ProcessManager2 = class {
39899
40070
  mergedEnv.PATH = "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin";
39900
40071
  console.log(`[ProcessManager] PATH was empty, set default: ${mergedEnv.PATH}`);
39901
40072
  }
39902
- const childProcess = spawn2(shell, ["-c", command], {
40073
+ const childProcess = spawn3(shell, ["-c", command], {
39903
40074
  cwd: workingDir,
39904
40075
  detached: true,
39905
40076
  // Run in separate process group
@@ -43655,7 +43826,6 @@ var IntegrationManager = class {
43655
43826
  messageRouter: this.deps.messageRouter,
43656
43827
  daemonName: this.deps.daemonName,
43657
43828
  getSlackSocketManager: this.deps.getSlackSocketManager,
43658
- getDaemon: this.deps.getDaemon,
43659
43829
  onConnected: async (provider, _services) => {
43660
43830
  if (provider === "google") {
43661
43831
  await this.startGoogleMcpServer();
@@ -43804,16 +43974,16 @@ var IntegrationManager = class {
43804
43974
  // src/managers/gmail-polling-store.ts
43805
43975
  import {
43806
43976
  existsSync as existsSync32,
43807
- mkdirSync as mkdirSync24,
43977
+ mkdirSync as mkdirSync23,
43808
43978
  readFileSync as readFileSync26,
43809
43979
  renameSync as renameSync3,
43810
43980
  statSync as statSync2,
43811
- unlinkSync as unlinkSync10,
43812
- writeFileSync as writeFileSync24
43981
+ unlinkSync as unlinkSync11,
43982
+ writeFileSync as writeFileSync25
43813
43983
  } from "fs";
43814
- import { homedir as homedir14 } from "os";
43984
+ import { homedir as homedir13 } from "os";
43815
43985
  import { dirname as dirname11, join as join33 } from "path";
43816
- var DEFAULT_STORAGE_DIR2 = join33(homedir14(), ".viyv-agent");
43986
+ var DEFAULT_STORAGE_DIR2 = join33(homedir13(), ".viyv-agent");
43817
43987
  var DEFAULT_STATE_FILE = "gmail-polling-state.json";
43818
43988
  var CURRENT_SCHEMA_VERSION2 = 1;
43819
43989
  var LOCK_TIMEOUT_MS = 60 * 1e3;
@@ -43845,7 +44015,7 @@ var GmailPollingStore = class {
43845
44015
  const lockAge = Date.now() - stat2.mtimeMs;
43846
44016
  if (lockAge > LOCK_TIMEOUT_MS) {
43847
44017
  console.log(`[GmailPollingStore] Removing stale lock (age: ${lockAge}ms)`);
43848
- unlinkSync10(this.lockPath);
44018
+ unlinkSync11(this.lockPath);
43849
44019
  } else {
43850
44020
  if (retry < LOCK_MAX_RETRIES - 1) {
43851
44021
  await this.sleep(LOCK_RETRY_DELAY_MS);
@@ -43858,7 +44028,7 @@ var GmailPollingStore = class {
43858
44028
  }
43859
44029
  }
43860
44030
  const lockData = JSON.stringify({ pid: process.pid, timestamp: Date.now() });
43861
- writeFileSync24(this.lockPath, lockData, { flag: "wx" });
44031
+ writeFileSync25(this.lockPath, lockData, { flag: "wx" });
43862
44032
  this.lockAcquired = true;
43863
44033
  return true;
43864
44034
  } catch (error) {
@@ -43882,7 +44052,7 @@ var GmailPollingStore = class {
43882
44052
  if (this.lockAcquired) {
43883
44053
  try {
43884
44054
  if (existsSync32(this.lockPath)) {
43885
- unlinkSync10(this.lockPath);
44055
+ unlinkSync11(this.lockPath);
43886
44056
  }
43887
44057
  } catch (error) {
43888
44058
  console.warn("[GmailPollingStore] Error releasing lock:", error);
@@ -43902,7 +44072,7 @@ var GmailPollingStore = class {
43902
44072
  async initialize() {
43903
44073
  const dir = dirname11(this.filePath);
43904
44074
  if (!existsSync32(dir)) {
43905
- mkdirSync24(dir, { recursive: true });
44075
+ mkdirSync23(dir, { recursive: true });
43906
44076
  console.log(`[GmailPollingStore] Created directory: ${dir}`);
43907
44077
  }
43908
44078
  if (!existsSync32(this.filePath)) {
@@ -43960,17 +44130,17 @@ var GmailPollingStore = class {
43960
44130
  try {
43961
44131
  const dir = dirname11(this.filePath);
43962
44132
  if (!existsSync32(dir)) {
43963
- mkdirSync24(dir, { recursive: true });
44133
+ mkdirSync23(dir, { recursive: true });
43964
44134
  }
43965
44135
  const uniqueSuffix = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
43966
44136
  const tempPath = `${this.filePath}.tmp.${uniqueSuffix}`;
43967
44137
  const content = JSON.stringify(this.data, null, 2);
43968
- writeFileSync24(tempPath, content, "utf-8");
44138
+ writeFileSync25(tempPath, content, "utf-8");
43969
44139
  try {
43970
44140
  renameSync3(tempPath, this.filePath);
43971
44141
  } catch (renameError) {
43972
44142
  try {
43973
- unlinkSync10(tempPath);
44143
+ unlinkSync11(tempPath);
43974
44144
  } catch {
43975
44145
  }
43976
44146
  throw renameError;
@@ -44935,8 +45105,6 @@ var Daemon = class _Daemon extends EventEmitter27 {
44935
45105
  preset;
44936
45106
  // Daemon mode: 'agent' (standalone) or 'team' (orchestrator + children)
44937
45107
  daemonMode = "team";
44938
- /** Chrome profile path for chrome-devtools MCP (per-daemon isolation) */
44939
- chromeProfilePath;
44940
45108
  // Managers (composition for modularity)
44941
45109
  commandDiscovery;
44942
45110
  commandSetup;
@@ -44954,6 +45122,10 @@ var Daemon = class _Daemon extends EventEmitter27 {
44954
45122
  autonomousLoopEngine;
44955
45123
  // Workspace Task Tools MCP Server for task management
44956
45124
  workspaceTaskToolsServer = null;
45125
+ // Browser MCP process (single SSE instance shared by all agents)
45126
+ browserMcpProcess = null;
45127
+ // Browser MCP URL from supervisor (for child daemons that don't own the process)
45128
+ _browserMcpUrl = null;
44957
45129
  constructor(instanceName, options) {
44958
45130
  super();
44959
45131
  this.state = loadConfig();
@@ -44963,7 +45135,7 @@ var Daemon = class _Daemon extends EventEmitter27 {
44963
45135
  const instanceId = instanceName ? this.generateStableInstanceId(this.state.config.nodeId, instanceName) : randomUUID18();
44964
45136
  const projectDir = getProjectDir(instanceId);
44965
45137
  if (!existsSync33(projectDir)) {
44966
- mkdirSync25(projectDir, { recursive: true });
45138
+ mkdirSync24(projectDir, { recursive: true });
44967
45139
  }
44968
45140
  this.runtimeState = {
44969
45141
  instanceId,
@@ -45023,7 +45195,6 @@ var Daemon = class _Daemon extends EventEmitter27 {
45023
45195
  const daemonConfig = instanceName ? getDaemonConfig(instanceName, this.state.config.workspaceId) : void 0;
45024
45196
  this.daemonType = daemonConfig?.type || "general" /* GENERAL */;
45025
45197
  this.daemonMode = daemonConfig?.mode || "team";
45026
- this.chromeProfilePath = daemonConfig?.chromeProfilePath;
45027
45198
  this.preset = getPreset(this.daemonType);
45028
45199
  console.log(`[Daemon] Loaded preset: ${this.preset.displayName} (${this.daemonType})`);
45029
45200
  console.log(`[Daemon] Mode: ${this.daemonMode === "agent" ? "Agent (standalone)" : "Team (orchestrator + children)"}`);
@@ -45210,7 +45381,6 @@ var Daemon = class _Daemon extends EventEmitter27 {
45210
45381
  messageRouter: this.messageRouter,
45211
45382
  daemonName: this.runtimeState.instanceName,
45212
45383
  getSlackSocketManager: () => this.slackSocketManager,
45213
- getDaemon: () => this,
45214
45384
  onSlackSetup: async () => {
45215
45385
  if (this.slackSocketManager) {
45216
45386
  console.log("[Daemon] Reconnecting Slack Socket Mode after token setup...");
@@ -45487,6 +45657,9 @@ var Daemon = class _Daemon extends EventEmitter27 {
45487
45657
  }
45488
45658
  return null;
45489
45659
  });
45660
+ this.ipcHandler.setBrowserMcpUrlCallback(() => {
45661
+ return this.getEffectiveBrowserMcpUrl();
45662
+ });
45490
45663
  try {
45491
45664
  this.slackSocketManager = new SlackSocketManager({
45492
45665
  apiUrl: this.state.config.enrollUrl,
@@ -45650,7 +45823,7 @@ var Daemon = class _Daemon extends EventEmitter27 {
45650
45823
  this.runtimeState.instanceId = newInstanceId;
45651
45824
  const newProjectDir = getProjectDir(newInstanceId);
45652
45825
  if (!existsSync33(newProjectDir)) {
45653
- mkdirSync25(newProjectDir, { recursive: true });
45826
+ mkdirSync24(newProjectDir, { recursive: true });
45654
45827
  }
45655
45828
  this.runtimeState.projectDir = newProjectDir;
45656
45829
  console.log(`[Daemon] Project directory: ${newProjectDir}`);
@@ -45734,8 +45907,22 @@ var Daemon = class _Daemon extends EventEmitter27 {
45734
45907
  } catch (error) {
45735
45908
  console.error("[Daemon] Failed to start WorkspaceTaskToolsServer:", error);
45736
45909
  }
45910
+ const supervisorBrowserMcpUrl = process.env.VIYV_BROWSER_MCP_URL;
45911
+ if (supervisorBrowserMcpUrl) {
45912
+ console.log(`[Daemon] Using supervisor's BrowserMcpProcess at ${supervisorBrowserMcpUrl}`);
45913
+ this._browserMcpUrl = supervisorBrowserMcpUrl;
45914
+ } else {
45915
+ try {
45916
+ this.browserMcpProcess = new BrowserMcpProcess();
45917
+ await this.browserMcpProcess.start();
45918
+ } catch (error) {
45919
+ console.error("[Daemon] Failed to start BrowserMcpProcess:", error);
45920
+ this.browserMcpProcess = null;
45921
+ }
45922
+ }
45737
45923
  const wsTaskToolsUrl = this.workspaceTaskToolsServer ? `http://127.0.0.1:${this.workspaceTaskToolsServer.getPort()}` : void 0;
45738
- await this.orchestrationManager.startOrchestrationServer(wsTaskToolsUrl, this.daemonMode);
45924
+ const browserMcpUrl = this.getEffectiveBrowserMcpUrl() || void 0;
45925
+ await this.orchestrationManager.startOrchestrationServer(wsTaskToolsUrl, this.daemonMode, browserMcpUrl);
45739
45926
  const orchestrationServer = this.orchestrationManager.getOrchestrationServer();
45740
45927
  if (orchestrationServer) {
45741
45928
  this.ipcHandler.setOrchestrationServer(orchestrationServer);
@@ -45801,52 +45988,48 @@ var Daemon = class _Daemon extends EventEmitter27 {
45801
45988
  ];
45802
45989
  /**
45803
45990
  * Merge agent config with default MCP servers and tools
45804
- * Ensures all agents have access to chrome-devtools MCP server
45991
+ * Ensures all agents have access to viyv-browser MCP server
45805
45992
  * Also adds workspace-task-tools for agents
45806
45993
  * Note: Planning Agent exclusion removed as Planning Agent has been deprecated
45807
45994
  */
45808
45995
  mergeAgentConfigWithDefaults(agentConfig) {
45809
45996
  const isSystemAgent = false;
45810
- let effectiveMcpServers = DEFAULT_MCP_SERVERS;
45811
- if (this.chromeProfilePath) {
45812
- const chromeConfig = DEFAULT_MCP_SERVERS["chrome-devtools"];
45813
- if (chromeConfig) {
45814
- effectiveMcpServers = {
45815
- ...DEFAULT_MCP_SERVERS,
45816
- "chrome-devtools": {
45817
- ...chromeConfig,
45818
- args: [...chromeConfig.args || [], "--user-data-dir", this.chromeProfilePath]
45819
- }
45820
- };
45821
- }
45822
- }
45823
- const workspaceTaskToolsMcp = {};
45997
+ const dynamicMcpServers = {};
45824
45998
  const workspaceTaskAllowedTools = [];
45825
45999
  if (this.workspaceTaskToolsServer && !isSystemAgent) {
45826
- workspaceTaskToolsMcp["workspace-task-tools"] = {
46000
+ dynamicMcpServers["workspace-task-tools"] = {
45827
46001
  type: "http",
45828
46002
  url: `http://127.0.0.1:${this.workspaceTaskToolsServer.getPort()}`
45829
46003
  };
45830
46004
  workspaceTaskAllowedTools.push(..._Daemon.WORKSPACE_TASK_ALLOWED_TOOLS);
45831
46005
  }
46006
+ const browserUrl = this.getEffectiveBrowserMcpUrl();
46007
+ if (browserUrl) {
46008
+ dynamicMcpServers["viyv-browser"] = {
46009
+ type: "sse",
46010
+ url: `${browserUrl}/sse`
46011
+ };
46012
+ }
45832
46013
  if (!agentConfig) {
45833
46014
  return {
45834
46015
  mcpServers: {
45835
- ...effectiveMcpServers,
45836
- ...workspaceTaskToolsMcp
46016
+ ...DEFAULT_MCP_SERVERS,
46017
+ ...dynamicMcpServers
45837
46018
  },
45838
- allowedTools: [...DEFAULT_CHROME_DEVTOOLS_TOOLS, ...workspaceTaskAllowedTools]
46019
+ allowedTools: [...DEFAULT_BROWSER_TOOLS, ...workspaceTaskAllowedTools]
45839
46020
  };
45840
46021
  }
45841
46022
  const existingMcpServers = agentConfig.mcpServers || {};
46023
+ delete existingMcpServers["chrome-devtools"];
46024
+ delete existingMcpServers["viyv-browser"];
45842
46025
  const mergedMcpServers = {
45843
- ...effectiveMcpServers,
45844
- ...workspaceTaskToolsMcp,
46026
+ ...DEFAULT_MCP_SERVERS,
46027
+ ...dynamicMcpServers,
45845
46028
  ...existingMcpServers
45846
46029
  };
45847
46030
  const existingAllowedTools = agentConfig.allowedTools || [];
45848
46031
  const mergedAllowedTools = [
45849
- .../* @__PURE__ */ new Set([...DEFAULT_CHROME_DEVTOOLS_TOOLS, ...workspaceTaskAllowedTools, ...existingAllowedTools])
46032
+ .../* @__PURE__ */ new Set([...DEFAULT_BROWSER_TOOLS, ...workspaceTaskAllowedTools, ...existingAllowedTools])
45850
46033
  ];
45851
46034
  return {
45852
46035
  ...agentConfig,
@@ -45854,12 +46037,6 @@ var Daemon = class _Daemon extends EventEmitter27 {
45854
46037
  allowedTools: mergedAllowedTools
45855
46038
  };
45856
46039
  }
45857
- /**
45858
- * Update Chrome profile path at runtime (called from integration message handler)
45859
- */
45860
- setChromeProfilePath(path18) {
45861
- this.chromeProfilePath = path18;
45862
- }
45863
46040
  /**
45864
46041
  * Sync shared commands to all existing workspaces
45865
46042
  * Delegates to CommandSetupManager
@@ -45992,6 +46169,14 @@ var Daemon = class _Daemon extends EventEmitter27 {
45992
46169
  console.error("[Daemon] Error stopping WorkspaceTaskToolsServer:", error);
45993
46170
  }
45994
46171
  }
46172
+ if (this.browserMcpProcess) {
46173
+ try {
46174
+ await this.browserMcpProcess.stop();
46175
+ console.log("[Daemon] BrowserMcpProcess stopped");
46176
+ } catch (error) {
46177
+ console.error("[Daemon] Error stopping BrowserMcpProcess:", error);
46178
+ }
46179
+ }
45995
46180
  for (const [processId] of this.agentProcesses) {
45996
46181
  await this.stopProcess(processId);
45997
46182
  }
@@ -46043,7 +46228,8 @@ var Daemon = class _Daemon extends EventEmitter27 {
46043
46228
  this.syncSystemAgentWorkspaces(true);
46044
46229
  const wsTaskToolsUrl = this.workspaceTaskToolsServer?.getPort() ? `http://127.0.0.1:${this.workspaceTaskToolsServer.getPort()}` : void 0;
46045
46230
  const googleMcpUrl = this.getEffectiveGoogleMcpUrl() || void 0;
46046
- this.orchestrationManager.updateMcpConfig(wsTaskToolsUrl, googleMcpUrl);
46231
+ const browserMcpUrl = this.getEffectiveBrowserMcpUrl() || void 0;
46232
+ this.orchestrationManager.updateMcpConfig(wsTaskToolsUrl, googleMcpUrl, browserMcpUrl);
46047
46233
  }
46048
46234
  /**
46049
46235
  * Subscribe to workspace ledger after cloud connection
@@ -46105,6 +46291,13 @@ var Daemon = class _Daemon extends EventEmitter27 {
46105
46291
  getLocalClientCount() {
46106
46292
  return this.socketServer.getClientCount();
46107
46293
  }
46294
+ /**
46295
+ * Get the effective Browser MCP URL
46296
+ * Returns URL from own process or from supervisor env var
46297
+ */
46298
+ getEffectiveBrowserMcpUrl() {
46299
+ return this.browserMcpProcess?.getUrl() ?? this._browserMcpUrl;
46300
+ }
46108
46301
  /**
46109
46302
  * Get the effective Google MCP server URL
46110
46303
  * Each daemon manages its own Google MCP server with daemon-scoped tokens
@@ -46118,6 +46311,13 @@ var Daemon = class _Daemon extends EventEmitter27 {
46118
46311
  */
46119
46312
  getMcpServersConfigForChildAgent() {
46120
46313
  const mcpServers = {};
46314
+ const browserMcpUrl = this.getEffectiveBrowserMcpUrl();
46315
+ if (browserMcpUrl) {
46316
+ mcpServers["viyv-browser"] = {
46317
+ type: "sse",
46318
+ url: `${browserMcpUrl}/sse`
46319
+ };
46320
+ }
46121
46321
  const googleMcpUrl = this.getEffectiveGoogleMcpUrl();
46122
46322
  if (googleMcpUrl) {
46123
46323
  mcpServers["viyv-google"] = {
@@ -49820,7 +50020,7 @@ function drawLogo() {
49820
50020
  }
49821
50021
 
49822
50022
  // src/cli/onboarding/welcome-screen.ts
49823
- var VERSION = "0.1.8";
50023
+ var VERSION = "0.1.9";
49824
50024
  function showCompactWelcome() {
49825
50025
  console.clear();
49826
50026
  emptyLines(1);
@@ -50042,7 +50242,7 @@ function truncateUrl(url, maxLen) {
50042
50242
  }
50043
50243
 
50044
50244
  // src/cli/index.ts
50045
- var PACKAGE_VERSION3 = "0.1.8";
50245
+ var PACKAGE_VERSION3 = "0.1.9";
50046
50246
  function formatUptime(ms) {
50047
50247
  const seconds = Math.floor(ms / 1e3);
50048
50248
  const minutes = Math.floor(seconds / 60);
@@ -50824,7 +51024,7 @@ function createCli() {
50824
51024
 
50825
51025
  // src/utils/update-checker.ts
50826
51026
  init_types();
50827
- import { existsSync as existsSync37, readFileSync as readFileSync29, writeFileSync as writeFileSync26, mkdirSync as mkdirSync27 } from "fs";
51027
+ import { existsSync as existsSync37, readFileSync as readFileSync29, writeFileSync as writeFileSync27, mkdirSync as mkdirSync26 } from "fs";
50828
51028
  var UPDATE_CHECK_INTERVAL = 24 * 60 * 60 * 1e3;
50829
51029
  var NPM_REGISTRY_URL = "https://registry.npmjs.org/viyv-daemon";
50830
51030
  function getUpdateCheckCachePath() {
@@ -50845,10 +51045,10 @@ function loadUpdateCheckCache() {
50845
51045
  function saveUpdateCheckCache(cache) {
50846
51046
  const configDir = getConfigDir();
50847
51047
  if (!existsSync37(configDir)) {
50848
- mkdirSync27(configDir, { recursive: true, mode: 448 });
51048
+ mkdirSync26(configDir, { recursive: true, mode: 448 });
50849
51049
  }
50850
51050
  const cachePath = getUpdateCheckCachePath();
50851
- writeFileSync26(cachePath, JSON.stringify(cache, null, 2), { mode: 384 });
51051
+ writeFileSync27(cachePath, JSON.stringify(cache, null, 2), { mode: 384 });
50852
51052
  }
50853
51053
  function compareVersions(a, b) {
50854
51054
  const parseVersion = (v) => {
@@ -50929,7 +51129,7 @@ function printUpdateNotice(info) {
50929
51129
 
50930
51130
  // src/index.ts
50931
51131
  process.noDeprecation = true;
50932
- var PACKAGE_VERSION4 = "0.1.8";
51132
+ var PACKAGE_VERSION4 = "0.1.9";
50933
51133
  var KNOWN_COMMANDS = [
50934
51134
  "start",
50935
51135
  "stop",