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.4",
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
- // Wrap MCP call in timeout to prevent indefinite hang (#13)
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 result = await callMCPTool('hooks_session-end', {
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 };