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 (written to ${msgPath}).` }]
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wogiflow",
3
- "version": "2.5.10",
3
+ "version": "2.6.0",
4
4
  "description": "AI-powered development workflow management system with multi-model support",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -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