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 +850 -650
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
1855
|
-
import { join as
|
|
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
|
|
2044
|
-
import { join as
|
|
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 =
|
|
2047
|
-
if (!
|
|
1860
|
+
const mcpJsonPath = join9(cwd, ".mcp.json");
|
|
1861
|
+
if (!existsSync9(mcpJsonPath)) {
|
|
2048
1862
|
return [];
|
|
2049
1863
|
}
|
|
2050
1864
|
try {
|
|
2051
|
-
const content =
|
|
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 =
|
|
2115
|
-
if (!
|
|
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 =
|
|
1934
|
+
const entries = readdirSync2(skillsDir, { withFileTypes: true });
|
|
2121
1935
|
for (const entry of entries) {
|
|
2122
1936
|
if (!entry.isDirectory()) continue;
|
|
2123
|
-
const skillMdPath =
|
|
2124
|
-
if (!
|
|
1937
|
+
const skillMdPath = join9(skillsDir, entry.name, "SKILL.md");
|
|
1938
|
+
if (!existsSync9(skillMdPath)) continue;
|
|
2125
1939
|
try {
|
|
2126
|
-
const content =
|
|
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 =
|
|
1983
|
+
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
2170
1984
|
for (const entry of entries) {
|
|
2171
|
-
const fullPath =
|
|
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 =
|
|
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 =
|
|
2011
|
+
const commandsDir = join9(cwd, ".claude", "commands");
|
|
2198
2012
|
const commands = [];
|
|
2199
|
-
if (!
|
|
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 =
|
|
2205
|
-
if (
|
|
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
|
|
6542
|
-
import { join as
|
|
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 (!
|
|
6545
|
-
|
|
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 ?
|
|
6549
|
-
if (definition.namespace && !
|
|
6550
|
-
|
|
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 =
|
|
6553
|
-
|
|
6366
|
+
const filePath = join15(targetDir, `${name}.md`);
|
|
6367
|
+
writeFileSync12(filePath, definition.content, "utf-8");
|
|
6554
6368
|
if (definition.metadata) {
|
|
6555
|
-
const metaPath =
|
|
6556
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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.
|
|
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
|
|
14916
|
-
mkdirSync as
|
|
14917
|
-
readFileSync as
|
|
14918
|
-
writeFileSync as
|
|
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 (!
|
|
14977
|
-
|
|
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 (
|
|
14985
|
-
const keyBase64 =
|
|
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
|
-
|
|
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
|
-
|
|
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 (!
|
|
15302
|
+
if (!existsSync5(configPath)) {
|
|
15061
15303
|
return null;
|
|
15062
15304
|
}
|
|
15063
15305
|
try {
|
|
15064
|
-
const content =
|
|
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 (
|
|
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
|
-
|
|
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 (!
|
|
15361
|
+
if (!existsSync5(tokenPath)) {
|
|
15120
15362
|
return null;
|
|
15121
15363
|
}
|
|
15122
15364
|
try {
|
|
15123
|
-
const content =
|
|
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
|
-
|
|
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 (
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
19569
|
-
import { dirname as
|
|
19570
|
-
import { homedir as
|
|
19571
|
-
import { randomUUID as
|
|
19572
|
-
var DEFAULT_STORAGE_DIR =
|
|
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 =
|
|
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 =
|
|
19589
|
-
if (!
|
|
19590
|
-
|
|
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 (!
|
|
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 =
|
|
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 =
|
|
19634
|
-
if (!
|
|
19635
|
-
|
|
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
|
-
|
|
19641
|
-
const { renameSync: renameSync5, unlinkSync:
|
|
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
|
-
|
|
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:
|
|
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
|
|
21523
|
-
import { join as
|
|
21524
|
-
import { homedir as
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
21762
|
-
import { homedir as
|
|
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(
|
|
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(
|
|
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 =
|
|
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
|
|
22340
|
-
import { homedir as
|
|
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
|
|
22347
|
-
import { homedir as
|
|
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(
|
|
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-${
|
|
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
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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-${
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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(
|
|
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 =
|
|
25917
|
-
const commandPath =
|
|
25918
|
-
if (!
|
|
25919
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
|
25999
|
-
if (
|
|
26000
|
-
|
|
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 (!
|
|
26005
|
-
|
|
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:
|
|
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 =
|
|
26169
|
+
targetPath = join16(commandsDir, parts[0], parts[1], `${parts[2]}.md`);
|
|
26026
26170
|
} else if (parts.length === 2) {
|
|
26027
|
-
targetPath =
|
|
26171
|
+
targetPath = join16(commandsDir, parts[0], `${parts[1]}.md`);
|
|
26028
26172
|
} else {
|
|
26029
26173
|
continue;
|
|
26030
26174
|
}
|
|
26031
|
-
if (
|
|
26032
|
-
|
|
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
|
|
28177
|
+
import { join as join18 } from "path";
|
|
28034
28178
|
|
|
28035
28179
|
// src/services/artifact-service.ts
|
|
28036
|
-
import { existsSync as
|
|
28037
|
-
import { join as
|
|
28038
|
-
import { createHash as createHash2, randomUUID as
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 (
|
|
28262
|
+
if (existsSync16(this.templatesDir)) {
|
|
28119
28263
|
try {
|
|
28120
|
-
const files =
|
|
28264
|
+
const files = readdirSync7(this.templatesDir);
|
|
28121
28265
|
for (const file of files) {
|
|
28122
28266
|
if (file.endsWith(".md")) {
|
|
28123
|
-
const filePath =
|
|
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 (
|
|
28144
|
-
const filePath =
|
|
28145
|
-
if (
|
|
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 (
|
|
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 (!
|
|
28307
|
+
if (!existsSync16(absolutePath)) {
|
|
28164
28308
|
return null;
|
|
28165
28309
|
}
|
|
28166
|
-
return
|
|
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 (
|
|
28176
|
-
const existingContent =
|
|
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 ||
|
|
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 =
|
|
28240
|
-
if (
|
|
28241
|
-
const content =
|
|
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 =
|
|
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}.${
|
|
28347
|
-
this.ensureDir(
|
|
28348
|
-
|
|
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 (!
|
|
28356
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
34713
|
-
|
|
34714
|
-
|
|
34715
|
-
|
|
34716
|
-
|
|
34717
|
-
|
|
34718
|
-
|
|
34719
|
-
|
|
34720
|
-
"
|
|
34721
|
-
"
|
|
34722
|
-
"
|
|
34723
|
-
"
|
|
34724
|
-
"
|
|
34725
|
-
"
|
|
34726
|
-
"
|
|
34727
|
-
"
|
|
34728
|
-
|
|
34729
|
-
|
|
34730
|
-
"
|
|
34731
|
-
"
|
|
34732
|
-
"
|
|
34733
|
-
"
|
|
34734
|
-
|
|
34735
|
-
"
|
|
34736
|
-
|
|
34737
|
-
|
|
34738
|
-
"
|
|
34739
|
-
"
|
|
34740
|
-
"
|
|
34741
|
-
|
|
34742
|
-
|
|
34743
|
-
"
|
|
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
|
-
// ★
|
|
34841
|
-
...
|
|
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
|
-
//
|
|
35210
|
-
...
|
|
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
|
|
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 (!
|
|
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 (
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
36214
|
+
writeFileSync17(refPath, ref.content, "utf-8");
|
|
36068
36215
|
}
|
|
36069
36216
|
const skillsDir = join22(baseDir, ".claude", "skills");
|
|
36070
36217
|
if (!existsSync21(skillsDir)) {
|
|
36071
|
-
|
|
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
|
-
|
|
36223
|
+
mkdirSync16(skillDir, { recursive: true });
|
|
36077
36224
|
}
|
|
36078
36225
|
const skillPath = join22(skillDir, "SKILL.md");
|
|
36079
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
36262
|
+
mkdirSync16(targetDir, { recursive: true });
|
|
36116
36263
|
}
|
|
36117
36264
|
const mdFilePath = join22(targetDir, `${name}.md`);
|
|
36118
|
-
|
|
36265
|
+
writeFileSync17(mdFilePath, definition.content, "utf-8");
|
|
36119
36266
|
if (definition.metadata) {
|
|
36120
36267
|
const metaFilePath = join22(targetDir, `${name}.meta.json`);
|
|
36121
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
36895
|
+
delete existingMcpServers["chrome-devtools"];
|
|
36896
|
+
const dynamicMcpServers = {};
|
|
36739
36897
|
if (workspaceTaskToolsUrl) {
|
|
36740
|
-
|
|
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
|
-
...
|
|
36914
|
+
...dynamicMcpServers,
|
|
36751
36915
|
"orchestration-tools": {
|
|
36752
36916
|
type: "http",
|
|
36753
36917
|
url: this.orchestrationServer.getUrl()
|
|
36754
36918
|
}
|
|
36755
36919
|
}
|
|
36756
36920
|
};
|
|
36757
|
-
|
|
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
|
-
|
|
36949
|
+
delete existingMcpServers["chrome-devtools"];
|
|
36950
|
+
const dynamicMcpServers = {};
|
|
36786
36951
|
if (workspaceTaskToolsUrl) {
|
|
36787
|
-
|
|
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
|
-
...
|
|
36968
|
+
...dynamicMcpServers
|
|
36798
36969
|
}
|
|
36799
36970
|
};
|
|
36800
|
-
|
|
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
|
|
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
|
-
|
|
37427
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
39534
|
+
mkdirSync20(dir, { recursive: true });
|
|
39364
39535
|
}
|
|
39365
|
-
|
|
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
|
|
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 =
|
|
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
|
|
43977
|
+
mkdirSync as mkdirSync23,
|
|
43808
43978
|
readFileSync as readFileSync26,
|
|
43809
43979
|
renameSync as renameSync3,
|
|
43810
43980
|
statSync as statSync2,
|
|
43811
|
-
unlinkSync as
|
|
43812
|
-
writeFileSync as
|
|
43981
|
+
unlinkSync as unlinkSync11,
|
|
43982
|
+
writeFileSync as writeFileSync25
|
|
43813
43983
|
} from "fs";
|
|
43814
|
-
import { homedir as
|
|
43984
|
+
import { homedir as homedir13 } from "os";
|
|
43815
43985
|
import { dirname as dirname11, join as join33 } from "path";
|
|
43816
|
-
var DEFAULT_STORAGE_DIR2 = join33(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
44138
|
+
writeFileSync25(tempPath, content, "utf-8");
|
|
43969
44139
|
try {
|
|
43970
44140
|
renameSync3(tempPath, this.filePath);
|
|
43971
44141
|
} catch (renameError) {
|
|
43972
44142
|
try {
|
|
43973
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
...
|
|
45836
|
-
...
|
|
46016
|
+
...DEFAULT_MCP_SERVERS,
|
|
46017
|
+
...dynamicMcpServers
|
|
45837
46018
|
},
|
|
45838
|
-
allowedTools: [...
|
|
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
|
-
...
|
|
45844
|
-
...
|
|
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([...
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
51048
|
+
mkdirSync26(configDir, { recursive: true, mode: 448 });
|
|
50849
51049
|
}
|
|
50850
51050
|
const cachePath = getUpdateCheckCachePath();
|
|
50851
|
-
|
|
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.
|
|
51132
|
+
var PACKAGE_VERSION4 = "0.1.9";
|
|
50933
51133
|
var KNOWN_COMMANDS = [
|
|
50934
51134
|
"start",
|
|
50935
51135
|
"stop",
|