wogiflow 2.5.10 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -270,8 +270,27 @@ function handleRequest(msg) {
|
|
|
270
270
|
};
|
|
271
271
|
const msgPath = require('node:path').join(messagesDir, `${msgId}.json`);
|
|
272
272
|
fs.writeFileSync(msgPath, JSON.stringify(msgObj, null, 2));
|
|
273
|
+
|
|
274
|
+
// Also POST to manager's channel port for real-time notification
|
|
275
|
+
const managerPort = process.env.WOGI_MANAGER_PORT;
|
|
276
|
+
if (managerPort) {
|
|
277
|
+
try {
|
|
278
|
+
const buf = Buffer.from(message, 'utf-8');
|
|
279
|
+
const req = http.request({
|
|
280
|
+
hostname: '127.0.0.1',
|
|
281
|
+
port: parseInt(managerPort, 10),
|
|
282
|
+
path: '/',
|
|
283
|
+
method: 'POST',
|
|
284
|
+
headers: { 'Content-Type': 'text/plain', 'Content-Length': buf.byteLength, 'X-Wogi-From': REPO_NAME }
|
|
285
|
+
});
|
|
286
|
+
req.on('error', () => { /* best effort */ });
|
|
287
|
+
req.write(buf);
|
|
288
|
+
req.end();
|
|
289
|
+
} catch (_err) { /* fallback is file */ }
|
|
290
|
+
}
|
|
291
|
+
|
|
273
292
|
sendResponse(msg.id, {
|
|
274
|
-
content: [{ type: 'text', text: `Message sent to manager (
|
|
293
|
+
content: [{ type: 'text', text: `Message sent to manager${managerPort ? ' (file + channel notification)' : ' (file only)'}.` }]
|
|
275
294
|
});
|
|
276
295
|
} catch (err) {
|
|
277
296
|
sendResponse(msg.id, {
|
package/lib/workspace.js
CHANGED
|
@@ -945,7 +945,8 @@ function generateMemberMcpConfigs(workspaceRoot, config) {
|
|
|
945
945
|
WOGI_CHANNEL_PORT: String(channelConfig.port),
|
|
946
946
|
WOGI_REPO_NAME: name,
|
|
947
947
|
WOGI_PEERS: peers,
|
|
948
|
-
WOGI_WORKSPACE_ROOT: workspaceRoot
|
|
948
|
+
WOGI_WORKSPACE_ROOT: workspaceRoot,
|
|
949
|
+
WOGI_MANAGER_PORT: String(config.channels.managerPort || (config.channels.basePort - 1))
|
|
949
950
|
}
|
|
950
951
|
}
|
|
951
952
|
}
|
|
@@ -1039,6 +1040,50 @@ For everything else — just do the work and report results.
|
|
|
1039
1040
|
fs.writeFileSync(path.join(rulesDir, 'worker-rules.md'), workerRule);
|
|
1040
1041
|
console.log(` ✓ ${name}/.claude/rules/workspace/worker-rules.md`);
|
|
1041
1042
|
}
|
|
1043
|
+
|
|
1044
|
+
// Generate .mcp.json at workspace root for the manager's channel server
|
|
1045
|
+
const managerPort = config.channels.managerPort || (config.channels.basePort - 1);
|
|
1046
|
+
let channelServerPath;
|
|
1047
|
+
try {
|
|
1048
|
+
channelServerPath = require.resolve('wogiflow/lib/workspace-channel-server.js');
|
|
1049
|
+
} catch (_err) {
|
|
1050
|
+
channelServerPath = path.join(__dirname, 'workspace-channel-server.js');
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
const allMembers = memberNames.map(n => `${n}:${channelMembers[n].port}`).join(',');
|
|
1054
|
+
const managerMcpConfig = {
|
|
1055
|
+
mcpServers: {
|
|
1056
|
+
'wogi-workspace-channel': {
|
|
1057
|
+
command: 'node',
|
|
1058
|
+
args: [channelServerPath],
|
|
1059
|
+
env: {
|
|
1060
|
+
WOGI_CHANNEL_PORT: String(managerPort),
|
|
1061
|
+
WOGI_REPO_NAME: 'manager',
|
|
1062
|
+
WOGI_PEERS: allMembers,
|
|
1063
|
+
WOGI_WORKSPACE_ROOT: workspaceRoot
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
};
|
|
1068
|
+
|
|
1069
|
+
// Merge with existing .mcp.json at workspace root
|
|
1070
|
+
const managerMcpPath = path.join(workspaceRoot, '.mcp.json');
|
|
1071
|
+
let existingManagerMcp = {};
|
|
1072
|
+
try {
|
|
1073
|
+
if (fs.existsSync(managerMcpPath)) {
|
|
1074
|
+
existingManagerMcp = JSON.parse(fs.readFileSync(managerMcpPath, 'utf-8'));
|
|
1075
|
+
}
|
|
1076
|
+
} catch (_err) { /* ignore */ }
|
|
1077
|
+
|
|
1078
|
+
const mergedManager = {
|
|
1079
|
+
...existingManagerMcp,
|
|
1080
|
+
mcpServers: {
|
|
1081
|
+
...(existingManagerMcp.mcpServers || {}),
|
|
1082
|
+
...managerMcpConfig.mcpServers
|
|
1083
|
+
}
|
|
1084
|
+
};
|
|
1085
|
+
fs.writeFileSync(managerMcpPath, JSON.stringify(mergedManager, null, 2));
|
|
1086
|
+
console.log(` ✓ .mcp.json (manager channel port ${managerPort}, workers: ${allMembers})`);
|
|
1042
1087
|
}
|
|
1043
1088
|
|
|
1044
1089
|
// ============================================================
|
|
@@ -1375,13 +1420,50 @@ function startWorkerSession(cwd) {
|
|
|
1375
1420
|
}
|
|
1376
1421
|
}
|
|
1377
1422
|
|
|
1423
|
+
// Manager mode: CWD is the workspace root itself (not a member)
|
|
1378
1424
|
if (!memberName || !memberChannel) {
|
|
1425
|
+
if (relativePath === '' || relativePath === '.') {
|
|
1426
|
+
// Start as workspace manager
|
|
1427
|
+
const managerPort = config.channels.managerPort || (config.channels.basePort - 1);
|
|
1428
|
+
const allMembers = Object.entries(config.channels.members)
|
|
1429
|
+
.map(([n, ch]) => `${n}:${ch.port}`)
|
|
1430
|
+
.join(',');
|
|
1431
|
+
|
|
1432
|
+
console.log(`Starting manager session (port ${managerPort})`);
|
|
1433
|
+
console.log(`Workers: ${allMembers}`);
|
|
1434
|
+
console.log('');
|
|
1435
|
+
|
|
1436
|
+
const env = {
|
|
1437
|
+
...process.env,
|
|
1438
|
+
WOGI_CHANNEL_PORT: String(managerPort),
|
|
1439
|
+
WOGI_REPO_NAME: 'manager',
|
|
1440
|
+
WOGI_PEERS: allMembers,
|
|
1441
|
+
WOGI_WORKSPACE_ROOT: workspaceRoot
|
|
1442
|
+
};
|
|
1443
|
+
|
|
1444
|
+
try {
|
|
1445
|
+
execSync('claude --dangerously-skip-permissions --dangerously-load-development-channels server:wogi-workspace-channel', {
|
|
1446
|
+
cwd,
|
|
1447
|
+
env,
|
|
1448
|
+
stdio: 'inherit'
|
|
1449
|
+
});
|
|
1450
|
+
} catch (err) {
|
|
1451
|
+
if (err.status && err.status !== 0 && err.signal !== 'SIGINT') {
|
|
1452
|
+
console.error(`Manager session exited with error (code ${err.status}): ${err.message}`);
|
|
1453
|
+
process.exit(err.status);
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1379
1459
|
console.error(`Error: Current directory "${relativePath}" does not match any workspace member.`);
|
|
1380
1460
|
console.error('Members:', Object.keys(config.members).join(', '));
|
|
1461
|
+
console.error('Or run from the workspace root to start as manager.');
|
|
1381
1462
|
process.exit(1);
|
|
1382
1463
|
}
|
|
1383
1464
|
|
|
1384
|
-
// Build peer list
|
|
1465
|
+
// Build peer list (include manager port)
|
|
1466
|
+
const managerPort = config.channels.managerPort || (config.channels.basePort - 1);
|
|
1385
1467
|
const peers = Object.entries(config.channels.members)
|
|
1386
1468
|
.filter(([n]) => n !== memberName)
|
|
1387
1469
|
.map(([n, ch]) => `${n}:${ch.port}`)
|
|
@@ -1415,6 +1497,7 @@ function startWorkerSession(cwd) {
|
|
|
1415
1497
|
WOGI_CHANNEL_PORT: String(memberChannel.port),
|
|
1416
1498
|
WOGI_REPO_NAME: memberName,
|
|
1417
1499
|
WOGI_PEERS: peers,
|
|
1500
|
+
WOGI_MANAGER_PORT: String(managerPort),
|
|
1418
1501
|
WOGI_WORKSPACE_ROOT: workspaceRoot
|
|
1419
1502
|
};
|
|
1420
1503
|
|
package/package.json
CHANGED
|
@@ -134,10 +134,35 @@ runHook('Stop', async ({ parsedInput }) => {
|
|
|
134
134
|
status: 'pending'
|
|
135
135
|
};
|
|
136
136
|
|
|
137
|
+
// Write to file (fallback / persistent record)
|
|
137
138
|
fs.writeFileSync(path.join(messagesDir, `${msgId}.json`), JSON.stringify(message, null, 2));
|
|
138
139
|
|
|
140
|
+
// Also HTTP POST to manager's channel port for real-time notification
|
|
141
|
+
// This makes the message appear as a prompt in the manager's session immediately
|
|
142
|
+
const managerPort = process.env.WOGI_MANAGER_PORT;
|
|
143
|
+
if (managerPort && repoName !== 'manager') {
|
|
144
|
+
try {
|
|
145
|
+
const http = require('node:http');
|
|
146
|
+
const body = Buffer.from(message.body, 'utf-8');
|
|
147
|
+
const req = http.request({
|
|
148
|
+
hostname: '127.0.0.1',
|
|
149
|
+
port: parseInt(managerPort, 10),
|
|
150
|
+
path: '/',
|
|
151
|
+
method: 'POST',
|
|
152
|
+
headers: {
|
|
153
|
+
'Content-Type': 'text/plain',
|
|
154
|
+
'Content-Length': body.byteLength,
|
|
155
|
+
'X-Wogi-From': repoName
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
req.on('error', () => { /* best effort — file is the fallback */ });
|
|
159
|
+
req.write(body);
|
|
160
|
+
req.end();
|
|
161
|
+
} catch (_err) { /* non-critical */ }
|
|
162
|
+
}
|
|
163
|
+
|
|
139
164
|
if (process.env.DEBUG) {
|
|
140
|
-
console.error(`[Stop] Workspace message written: ${msgId}`);
|
|
165
|
+
console.error(`[Stop] Workspace message written: ${msgId}${managerPort ? ` + HTTP to manager:${managerPort}` : ''}`);
|
|
141
166
|
}
|
|
142
167
|
} catch (err) {
|
|
143
168
|
// Non-critical — best effort
|