wogiflow 2.6.0 → 2.6.1
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/lib/workspace.js +17 -7
- package/package.json +1 -1
- package/scripts/hooks/entry/claude-code/stop.js +27 -78
package/lib/workspace.js
CHANGED
|
@@ -990,22 +990,32 @@ description: "Workspace worker rules — reply to manager after every channel ta
|
|
|
990
990
|
|
|
991
991
|
You are **${name}** in a Wogi Workspace managed by an orchestrator.
|
|
992
992
|
|
|
993
|
-
## CRITICAL: Always Reply to the Manager
|
|
993
|
+
## CRITICAL: Always Reply to the Manager (port ${config.channels.managerPort || (config.channels.basePort - 1)})
|
|
994
994
|
|
|
995
|
-
When you receive a message via the workspace channel
|
|
995
|
+
When you receive a message via the workspace channel, you MUST send results back to the manager after completing the work. **The user only sees the manager terminal — if you don't reply, they never see your results.**
|
|
996
996
|
|
|
997
|
-
|
|
997
|
+
**PRIMARY method — curl to manager port (always works, even if MCP tools haven't loaded yet):**
|
|
998
|
+
|
|
999
|
+
\`\`\`bash
|
|
1000
|
+
curl -s -X POST http://localhost:${config.channels.managerPort || (config.channels.basePort - 1)} -H "Content-Type: text/plain" -H "X-Wogi-From: ${name}" -d "## Results
|
|
1001
|
+
|
|
1002
|
+
[your findings/summary here]"
|
|
1003
|
+
\`\`\`
|
|
1004
|
+
|
|
1005
|
+
**ALTERNATIVE — workspace_send_message MCP tool (if available):**
|
|
998
1006
|
|
|
999
1007
|
\`\`\`
|
|
1000
1008
|
workspace_send_message(to: "manager", message: "## Results\\n\\n[your findings/summary here]")
|
|
1001
1009
|
\`\`\`
|
|
1002
1010
|
|
|
1003
|
-
|
|
1011
|
+
If the MCP tool is not available (shows "MCP servers still connecting"), use the curl command. **Do NOT write JSON files to .workspace/messages/ directly — that doesn't notify the manager.**
|
|
1012
|
+
|
|
1013
|
+
This is NON-OPTIONAL. Every channel-dispatched task MUST end with a reply to the manager.
|
|
1004
1014
|
|
|
1005
1015
|
## Peer Communication
|
|
1006
1016
|
|
|
1007
|
-
You can talk to peer repos
|
|
1008
|
-
${peerNames.map(p => `- \`
|
|
1017
|
+
You can talk to peer repos via curl or the MCP tool:
|
|
1018
|
+
${peerNames.map(p => `- \`curl -s -X POST http://localhost:${channelMembers[p]?.port || '???'} -H "X-Wogi-From: ${name}" -d "your message"\``).join('\n')}
|
|
1009
1019
|
|
|
1010
1020
|
## Autonomous Mode — Auto-Approve Everything
|
|
1011
1021
|
|
|
@@ -1024,7 +1034,7 @@ Only send a question to the manager (instead of results) when:
|
|
|
1024
1034
|
- The task requires **deleting user data** or making irreversible changes
|
|
1025
1035
|
- You are genuinely **stuck** and cannot proceed
|
|
1026
1036
|
|
|
1027
|
-
To escalate: \`
|
|
1037
|
+
To escalate: \`curl -s -X POST http://localhost:${config.channels.managerPort || (config.channels.basePort - 1)} -H "X-Wogi-From: ${name}" -d "## Need Decision: [describe the choice and options]"\`
|
|
1028
1038
|
|
|
1029
1039
|
For everything else — just do the work and report results.
|
|
1030
1040
|
|
package/package.json
CHANGED
|
@@ -61,22 +61,19 @@ runHook('Stop', async ({ parsedInput }) => {
|
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
// Workspace worker:
|
|
65
|
-
//
|
|
66
|
-
// The
|
|
67
|
-
|
|
68
|
-
if (process.env.WOGI_WORKSPACE_ROOT && process.env.WOGI_REPO_NAME) {
|
|
64
|
+
// Workspace worker: send results to manager via HTTP when stopping.
|
|
65
|
+
// Uses synchronous curl to guarantee delivery before the hook process exits.
|
|
66
|
+
// The async http.request approach was unreliable — process exited before request completed.
|
|
67
|
+
if (process.env.WOGI_MANAGER_PORT && process.env.WOGI_REPO_NAME && process.env.WOGI_REPO_NAME !== 'manager') {
|
|
69
68
|
try {
|
|
69
|
+
const { execSync } = require('node:child_process');
|
|
70
70
|
const fs = require('node:fs');
|
|
71
71
|
const path = require('node:path');
|
|
72
|
-
const crypto = require('node:crypto');
|
|
73
|
-
const workspaceRoot = process.env.WOGI_WORKSPACE_ROOT;
|
|
74
72
|
const repoName = process.env.WOGI_REPO_NAME;
|
|
75
|
-
const
|
|
76
|
-
fs.mkdirSync(messagesDir, { recursive: true });
|
|
73
|
+
const managerPort = process.env.WOGI_MANAGER_PORT;
|
|
77
74
|
|
|
78
75
|
// Build summary from available state
|
|
79
|
-
const
|
|
76
|
+
const summaryParts = [];
|
|
80
77
|
const { PATHS, safeJsonParse } = require('../../flow-utils');
|
|
81
78
|
|
|
82
79
|
// Get current/recently completed task info
|
|
@@ -86,88 +83,40 @@ runHook('Stop', async ({ parsedInput }) => {
|
|
|
86
83
|
const task = recentTask || inProgressTask;
|
|
87
84
|
|
|
88
85
|
if (task) {
|
|
89
|
-
|
|
90
|
-
if (task.type)
|
|
86
|
+
summaryParts.push(`**Task**: ${task.title || task.id}`);
|
|
87
|
+
if (task.type) summaryParts.push(`**Type**: ${task.type}`);
|
|
91
88
|
}
|
|
92
89
|
|
|
93
|
-
// Get
|
|
94
|
-
try {
|
|
95
|
-
const logPath = path.join(PATHS.root, 'request-log.md');
|
|
96
|
-
if (fs.existsSync(logPath)) {
|
|
97
|
-
const stat = fs.statSync(logPath);
|
|
98
|
-
if (stat.size < 200 * 1024) {
|
|
99
|
-
const logContent = fs.readFileSync(logPath, 'utf-8');
|
|
100
|
-
const parts = logContent.split(/^### R-/m);
|
|
101
|
-
if (parts.length > 1) {
|
|
102
|
-
const lastEntry = parts[parts.length - 1];
|
|
103
|
-
if (lastEntry.length < 2000) {
|
|
104
|
-
summary.push(`**Log entry**:\n### R-${lastEntry.trim()}`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
} catch (_err) { /* non-critical */ }
|
|
110
|
-
|
|
111
|
-
// Get git status for changed files
|
|
90
|
+
// Get changed files
|
|
112
91
|
try {
|
|
113
|
-
const { execSync } = require('node:child_process');
|
|
114
92
|
const diff = execSync('git diff --name-only HEAD 2>/dev/null || true', { cwd: PATHS.root, encoding: 'utf-8' }).trim();
|
|
115
93
|
const staged = execSync('git diff --name-only --staged 2>/dev/null || true', { cwd: PATHS.root, encoding: 'utf-8' }).trim();
|
|
116
94
|
const allChanged = [...new Set([...diff.split('\n'), ...staged.split('\n')].filter(Boolean))];
|
|
117
95
|
if (allChanged.length > 0) {
|
|
118
|
-
|
|
96
|
+
summaryParts.push(`**Files changed**: ${allChanged.join(', ')}`);
|
|
119
97
|
}
|
|
120
98
|
} catch (_err) { /* non-critical */ }
|
|
121
99
|
|
|
122
|
-
const
|
|
123
|
-
const message = {
|
|
124
|
-
id: msgId,
|
|
125
|
-
from: repoName,
|
|
126
|
-
to: 'manager',
|
|
127
|
-
type: 'task-complete',
|
|
128
|
-
priority: 'medium',
|
|
129
|
-
timestamp: new Date().toISOString(),
|
|
130
|
-
subject: task ? `Completed: ${task.title || task.id}` : `Work completed by ${repoName}`,
|
|
131
|
-
body: summary.join('\n') || `${repoName} finished processing.`,
|
|
132
|
-
taskId: task?.id || null,
|
|
133
|
-
actionRequired: false,
|
|
134
|
-
status: 'pending'
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
// Write to file (fallback / persistent record)
|
|
138
|
-
fs.writeFileSync(path.join(messagesDir, `${msgId}.json`), JSON.stringify(message, null, 2));
|
|
100
|
+
const body = summaryParts.join('\n') || `${repoName} finished processing.`;
|
|
139
101
|
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
164
|
-
if (process.env.DEBUG) {
|
|
165
|
-
console.error(`[Stop] Workspace message written: ${msgId}${managerPort ? ` + HTTP to manager:${managerPort}` : ''}`);
|
|
102
|
+
// PRIMARY: Synchronous curl to manager port — guaranteed to complete before exit
|
|
103
|
+
try {
|
|
104
|
+
execSync(
|
|
105
|
+
`curl -s -X POST http://127.0.0.1:${managerPort} -H "Content-Type: text/plain" -H "X-Wogi-From: ${repoName}" --data-binary @-`,
|
|
106
|
+
{ input: body, timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] }
|
|
107
|
+
);
|
|
108
|
+
if (process.env.DEBUG) {
|
|
109
|
+
console.error(`[Stop] Sent results to manager via curl :${managerPort}`);
|
|
110
|
+
}
|
|
111
|
+
} catch (_err) {
|
|
112
|
+
// Manager might be offline — that's OK
|
|
113
|
+
if (process.env.DEBUG) {
|
|
114
|
+
console.error(`[Stop] curl to manager:${managerPort} failed: ${_err.message}`);
|
|
115
|
+
}
|
|
166
116
|
}
|
|
167
117
|
} catch (err) {
|
|
168
|
-
// Non-critical — best effort
|
|
169
118
|
if (process.env.DEBUG) {
|
|
170
|
-
console.error(`[Stop] Workspace
|
|
119
|
+
console.error(`[Stop] Workspace notification failed: ${err.message}`);
|
|
171
120
|
}
|
|
172
121
|
}
|
|
173
122
|
}
|