moflo 4.0.4 → 4.0.5
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "moflo",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.5",
|
|
4
4
|
"description": "MoFlo — AI agent orchestration for Claude Code. Forked from ruflo/claude-flow with patches applied to source, plus feature-level orchestration.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -59,8 +59,7 @@ const preEditCommand = {
|
|
|
59
59
|
output.printInfo(`Analyzing context for: ${output.highlight(filePath)}`);
|
|
60
60
|
try {
|
|
61
61
|
// Call MCP tool for pre-edit hook
|
|
62
|
-
|
|
63
|
-
const mcpPromise = callMCPTool('hooks_pre-edit', {
|
|
62
|
+
const result = await callMCPTool('hooks_pre-edit', {
|
|
64
63
|
filePath,
|
|
65
64
|
operation,
|
|
66
65
|
context: ctx.flags.context,
|
|
@@ -72,125 +71,6 @@ const preEditCommand = {
|
|
|
72
71
|
return { success: true, data: result };
|
|
73
72
|
}
|
|
74
73
|
output.writeln();
|
|
75
|
-
output.printBox([
|
|
76
|
-
`File: ${result.filePath}`,
|
|
77
|
-
`Operation: ${result.operation}`,
|
|
78
|
-
`Type: ${result.context.fileType}`,
|
|
79
|
-
`Exists: ${result.context.fileExists ? 'Yes' : 'No'}`
|
|
80
|
-
].join('\n'), 'File Context');
|
|
81
|
-
if (result.context.suggestedAgents.length > 0) {
|
|
82
|
-
output.writeln();
|
|
83
|
-
output.writeln(output.bold('Suggested Agents'));
|
|
84
|
-
output.printList(result.context.suggestedAgents.map(a => output.highlight(a)));
|
|
85
|
-
}
|
|
86
|
-
if (result.context.relatedFiles.length > 0) {
|
|
87
|
-
output.writeln();
|
|
88
|
-
output.writeln(output.bold('Related Files'));
|
|
89
|
-
output.printList(result.context.relatedFiles.slice(0, 5).map(f => output.dim(f)));
|
|
90
|
-
}
|
|
91
|
-
if (result.context.patterns.length > 0) {
|
|
92
|
-
output.writeln();
|
|
93
|
-
output.writeln(output.bold('Learned Patterns'));
|
|
94
|
-
output.printTable({
|
|
95
|
-
columns: [
|
|
96
|
-
{ key: 'pattern', header: 'Pattern', width: 40 },
|
|
97
|
-
{ key: 'confidence', header: 'Confidence', width: 12, align: 'right', format: (v) => `${(Number(v) * 100).toFixed(1)}%` }
|
|
98
|
-
],
|
|
99
|
-
data: result.context.patterns
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
if (result.context.risks.length > 0) {
|
|
103
|
-
output.writeln();
|
|
104
|
-
output.writeln(output.bold(output.error('Potential Risks')));
|
|
105
|
-
output.printList(result.context.risks.map(r => output.warning(r)));
|
|
106
|
-
}
|
|
107
|
-
if (result.recommendations.length > 0) {
|
|
108
|
-
output.writeln();
|
|
109
|
-
output.writeln(output.bold('Recommendations'));
|
|
110
|
-
output.printList(result.recommendations.map(r => output.success(`• ${r}`)));
|
|
111
|
-
}
|
|
112
|
-
return { success: true, data: result };
|
|
113
|
-
}
|
|
114
|
-
catch (error) {
|
|
115
|
-
if (error instanceof MCPClientError) {
|
|
116
|
-
output.printError(`Pre-edit hook failed: ${error.message}`);
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
output.printError(`Unexpected error: ${String(error)}`);
|
|
120
|
-
}
|
|
121
|
-
return { success: false, exitCode: 1 };
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
// Post-edit subcommand
|
|
126
|
-
const postEditCommand = {
|
|
127
|
-
name: 'post-edit',
|
|
128
|
-
description: 'Record editing outcome for learning',
|
|
129
|
-
options: [
|
|
130
|
-
{
|
|
131
|
-
name: 'file',
|
|
132
|
-
short: 'f',
|
|
133
|
-
description: 'File path that was edited',
|
|
134
|
-
type: 'string',
|
|
135
|
-
required: false
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
name: 'success',
|
|
139
|
-
short: 's',
|
|
140
|
-
description: 'Whether the edit was successful',
|
|
141
|
-
type: 'boolean',
|
|
142
|
-
required: false
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
name: 'outcome',
|
|
146
|
-
short: 'o',
|
|
147
|
-
description: 'Outcome description',
|
|
148
|
-
type: 'string'
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
name: 'metrics',
|
|
152
|
-
short: 'm',
|
|
153
|
-
description: 'Performance metrics (e.g., "time:500ms,quality:0.95")',
|
|
154
|
-
type: 'string'
|
|
155
|
-
}
|
|
156
|
-
],
|
|
157
|
-
examples: [
|
|
158
|
-
{ command: 'claude-flow hooks post-edit -f src/utils.ts --success true', description: 'Record successful edit' },
|
|
159
|
-
{ command: 'claude-flow hooks post-edit -f src/api.ts --success false -o "Type error"', description: 'Record failed edit' }
|
|
160
|
-
],
|
|
161
|
-
action: async (ctx) => {
|
|
162
|
-
// Default file to 'unknown' for backward compatibility (env var may be empty)
|
|
163
|
-
const filePath = ctx.args[0] || ctx.flags.file || 'unknown';
|
|
164
|
-
// Default success to true for backward compatibility (PostToolUse = success, PostToolUseFailure = failure)
|
|
165
|
-
const success = ctx.flags.success !== undefined ? ctx.flags.success : true;
|
|
166
|
-
output.printInfo(`Recording outcome for: ${output.highlight(filePath)}`);
|
|
167
|
-
try {
|
|
168
|
-
// Parse metrics if provided
|
|
169
|
-
const metrics = {};
|
|
170
|
-
if (ctx.flags.metrics) {
|
|
171
|
-
const metricsStr = ctx.flags.metrics;
|
|
172
|
-
metricsStr.split(',').forEach(pair => {
|
|
173
|
-
const [key, value] = pair.split(':');
|
|
174
|
-
if (key && value) {
|
|
175
|
-
metrics[key.trim()] = parseFloat(value);
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
// Call MCP tool for post-edit hook
|
|
180
|
-
const result = await callMCPTool('hooks_post-edit', {
|
|
181
|
-
filePath,
|
|
182
|
-
success,
|
|
183
|
-
outcome: ctx.flags.outcome,
|
|
184
|
-
metrics,
|
|
185
|
-
timestamp: Date.now(),
|
|
186
|
-
});
|
|
187
|
-
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('session-end timed out after 3s')), 3000));
|
|
188
|
-
const result = await Promise.race([mcpPromise, timeoutPromise]);
|
|
189
|
-
if (ctx.flags.format === 'json') {
|
|
190
|
-
output.printJson(result);
|
|
191
|
-
return { success: true, data: result };
|
|
192
|
-
}
|
|
193
|
-
output.writeln();
|
|
194
74
|
output.printSuccess(`Outcome recorded for ${filePath}`);
|
|
195
75
|
if (result.learningUpdates) {
|
|
196
76
|
output.writeln();
|
|
@@ -1383,10 +1263,12 @@ const sessionEndCommand = {
|
|
|
1383
1263
|
action: async (ctx) => {
|
|
1384
1264
|
output.printInfo('Ending session...');
|
|
1385
1265
|
try {
|
|
1386
|
-
const
|
|
1266
|
+
const mcpPromise = callMCPTool('hooks_session-end', {
|
|
1387
1267
|
saveState: ctx.flags.saveState ?? true,
|
|
1388
1268
|
timestamp: Date.now(),
|
|
1389
1269
|
});
|
|
1270
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('session-end timed out after 3s')), 3000));
|
|
1271
|
+
const result = await Promise.race([mcpPromise, timeoutPromise]);
|
|
1390
1272
|
if (ctx.flags.format === 'json') {
|
|
1391
1273
|
output.printJson(result);
|
|
1392
1274
|
return { success: true, data: result };
|