multi-agents-cli 1.1.71 → 1.1.73
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/ui.js +49 -32
- package/lib/validate.js +44 -1
- package/package.json +1 -1
package/lib/ui.js
CHANGED
|
@@ -121,7 +121,7 @@ const stepHeader = (stepIndex, totalSteps) => {
|
|
|
121
121
|
// ── Step selection helpers ────────────────────────────────────────────────────
|
|
122
122
|
|
|
123
123
|
const { BACK, RESTART } = require('./steps');
|
|
124
|
-
const { validateCombination,
|
|
124
|
+
const { validateCombination, resolveFramework } = require('./validate');
|
|
125
125
|
const { BLOCKS } = require('./data-config');
|
|
126
126
|
|
|
127
127
|
const NONE_LABEL = '→ None of these - I\'ll specify my own';
|
|
@@ -133,47 +133,64 @@ const handleFreeText = async (prompt, items, stepMachine, stepIndex, context, is
|
|
|
133
133
|
const typed = (_res.value || '').trim();
|
|
134
134
|
if (!typed) return isOptional ? null : handleFreeText(prompt, items, stepMachine, stepIndex, context, isOptional, block);
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
136
|
+
console.log(dim(' Verifying...'));
|
|
137
|
+
const resolved = await resolveFramework(typed, block);
|
|
138
|
+
|
|
139
|
+
if (resolved.status === 'fuzzy') {
|
|
140
|
+
const opts = [
|
|
141
|
+
...resolved.matches.map(m => `→ ${m.label || m}`),
|
|
141
142
|
`→ Type a different value`,
|
|
142
143
|
];
|
|
143
|
-
const choice = await arrowSelect(`"${typed}" couldn't be verified. Did you mean:`,
|
|
144
|
-
if (choice < matches.length) return matches[choice];
|
|
144
|
+
const choice = await arrowSelect(`"${typed}" couldn't be verified. Did you mean:`, opts.map(o => ({ label: o })));
|
|
145
|
+
if (choice < resolved.matches.length) return resolved.matches[choice];
|
|
145
146
|
return handleFreeText(prompt, items, stepMachine, stepIndex, context, isOptional, block);
|
|
146
147
|
}
|
|
147
148
|
|
|
148
|
-
|
|
149
|
-
console.log(dim(' Verifying...'));
|
|
150
|
-
const existence = await checkFrameworkExists(typed);
|
|
149
|
+
if (resolved.status === 'valid') return resolved.match;
|
|
151
150
|
|
|
152
|
-
if (
|
|
153
|
-
console.log('');
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
`→
|
|
157
|
-
];
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
console.log(
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
{ label: `→ Yes - proceed with "${typed}"` },
|
|
170
|
-
{ label: `→ No - let me pick something else` },
|
|
151
|
+
if (resolved.status === 'partial_cross') {
|
|
152
|
+
console.log(`\n ${yellow('⚠')} ${resolved.message}\n`);
|
|
153
|
+
const choice = await arrowSelect(`"${typed}" couldn't be verified.`, [
|
|
154
|
+
{ label: `→ Type a different value` },
|
|
155
|
+
{ label: `→ Choose from the ${block} list` },
|
|
156
|
+
]);
|
|
157
|
+
if (choice === 1) return null;
|
|
158
|
+
return handleFreeText(prompt, items, stepMachine, stepIndex, context, isOptional, block);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (resolved.status === 'cross_block') {
|
|
162
|
+
console.log(`
|
|
163
|
+
${yellow('⚠')} ${resolved.message}
|
|
164
|
+
`);
|
|
165
|
+
const choice = await arrowSelect('How would you like to proceed?', [
|
|
166
|
+
{ label: `→ Continue - I understand the tradeoff` },
|
|
167
|
+
{ label: `→ Type a different value` },
|
|
171
168
|
]);
|
|
172
|
-
if (
|
|
169
|
+
if (choice === 1) return handleFreeText(prompt, items, stepMachine, stepIndex, context, isOptional, block);
|
|
173
170
|
return typed;
|
|
174
171
|
}
|
|
175
172
|
|
|
176
|
-
//
|
|
173
|
+
// unverified - risk block
|
|
174
|
+
console.log('');
|
|
175
|
+
const riskOpts = [
|
|
176
|
+
`→ Proceed with "${typed}" - I accept the risks`,
|
|
177
|
+
`→ Type a different value`,
|
|
178
|
+
];
|
|
179
|
+
const riskChoice = await arrowSelect(`"${typed}" couldn't be verified.`, riskOpts.map(o => ({ label: o })));
|
|
180
|
+
if (riskChoice === 1) return handleFreeText(prompt, items, stepMachine, stepIndex, context, isOptional, block);
|
|
181
|
+
console.log('');
|
|
182
|
+
console.log(` ${yellow('⚠ Proceeding with an unverified framework may result in:')}`);
|
|
183
|
+
console.log(dim(' · Agent spending excessive tokens resolving unknown setup'));
|
|
184
|
+
console.log(dim(' · Incorrect scaffold structure for this framework'));
|
|
185
|
+
console.log(dim(' · Missing contracts and integration points'));
|
|
186
|
+
console.log(dim(' · Potential mid-flow failures requiring full restart'));
|
|
187
|
+
console.log('');
|
|
188
|
+
const confirm = await arrowSelect('Confirm you understand and want to continue?', [
|
|
189
|
+
{ label: `→ Yes - proceed with "${typed}"` },
|
|
190
|
+
{ label: `→ No - let me pick something else` },
|
|
191
|
+
]);
|
|
192
|
+
if (confirm === 1) return handleFreeText(prompt, items, stepMachine, stepIndex, context, isOptional, block);
|
|
193
|
+
|
|
177
194
|
const check = validateCombination(typed, context);
|
|
178
195
|
if (!check.valid) {
|
|
179
196
|
console.log(`
|
package/lib/validate.js
CHANGED
|
@@ -127,4 +127,47 @@ const validateCombination = (chosen, context = {}) => {
|
|
|
127
127
|
return { valid: true, reason: null, alternatives: [] };
|
|
128
128
|
};
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
|
|
131
|
+
// ── resolveFramework ──────────────────────────────────────────────────────────
|
|
132
|
+
// Full lookup order per block — returns { status, match, message }
|
|
133
|
+
// status: 'match' | 'cross_block' | 'partial_cross' | 'unverified' | 'valid'
|
|
134
|
+
|
|
135
|
+
const resolveFramework = async (typed, block = null) => {
|
|
136
|
+
const lower = typed.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
137
|
+
|
|
138
|
+
const primaryPool = block === BLOCKS.CLIENT ? CLIENT_FRAMEWORKS
|
|
139
|
+
: block === BLOCKS.BACKEND ? BACKEND_FRAMEWORKS
|
|
140
|
+
: ALL_FRAMEWORKS;
|
|
141
|
+
const secondaryPool = block === BLOCKS.CLIENT ? BACKEND_FRAMEWORKS
|
|
142
|
+
: block === BLOCKS.BACKEND ? CLIENT_FRAMEWORKS
|
|
143
|
+
: [];
|
|
144
|
+
const crossLabel = block === BLOCKS.CLIENT ? 'backend' : 'client';
|
|
145
|
+
|
|
146
|
+
// 1. Fuzzy match in primary pool
|
|
147
|
+
const primaryFuzzy = primaryPool.filter(f => {
|
|
148
|
+
const n = f.value.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
149
|
+
return n.includes(lower) || lower.includes(n) || (lower.length >= 3 && n.startsWith(lower.slice(0, 3)));
|
|
150
|
+
}).slice(0, 3);
|
|
151
|
+
if (primaryFuzzy.length > 0) return { status: 'fuzzy', matches: primaryFuzzy, message: null };
|
|
152
|
+
|
|
153
|
+
// 2. Exact match in primary pool
|
|
154
|
+
const primaryExact = primaryPool.find(f => f.value.toLowerCase() === typed.toLowerCase());
|
|
155
|
+
if (primaryExact) return { status: 'valid', match: primaryExact, message: null };
|
|
156
|
+
|
|
157
|
+
// 3. Partial match in secondary pool
|
|
158
|
+
const secondaryFuzzy = secondaryPool.filter(f => {
|
|
159
|
+
const n = f.value.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
160
|
+
return n.includes(lower) || lower.includes(n) || (lower.length >= 3 && n.startsWith(lower.slice(0, 3)));
|
|
161
|
+
});
|
|
162
|
+
if (secondaryFuzzy.length > 0) return { status: 'partial_cross', matches: secondaryFuzzy, message: `No such ${block} framework found. Did you mean a ${crossLabel} framework?` };
|
|
163
|
+
|
|
164
|
+
// 4. Exact match in secondary pool
|
|
165
|
+
const secondaryExact = secondaryPool.find(f => f.value.toLowerCase() === typed.toLowerCase());
|
|
166
|
+
if (secondaryExact) return { status: 'cross_block', match: secondaryExact, message: `"${typed}" is a ${crossLabel} framework, not a ${block} framework.` };
|
|
167
|
+
|
|
168
|
+
// 5. Registry check
|
|
169
|
+
const existence = await checkFrameworkExists(typed);
|
|
170
|
+
return { status: 'unverified', match: null, message: existence.exists ? `"${typed}" was found on ${existence.registry} but could not be confirmed as a ${block || ''} framework.` : `"${typed}" couldn't be verified on any registry.` };
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
module.exports = { validateCombination, checkFrameworkExists, fuzzyMatchFramework, resolveFramework };
|
package/package.json
CHANGED