accio-context 1.0.0 → 1.0.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/package.json +1 -1
- package/src/cli.js +108 -23
- package/src/install.js +2 -0
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ const prompts = require("prompts");
|
|
|
5
5
|
const YAML = require("yaml");
|
|
6
6
|
|
|
7
7
|
const { getInventory } = require("./inventory");
|
|
8
|
-
const { buildCopyPlan, executeCopyPlan } = require("./install");
|
|
8
|
+
const { buildCopyPlan, executeCopyPlan, collectSkillItems, collectTemplateItems } = require("./install");
|
|
9
9
|
const { getRepoRoot } = require("./repo");
|
|
10
10
|
|
|
11
11
|
async function loadConfig(configPath) {
|
|
@@ -41,7 +41,7 @@ function printList(inventory) {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
async function promptSelections(inventory) {
|
|
44
|
+
async function promptSelections(inventory, targetRoot, options) {
|
|
45
45
|
const selections = { domains: [], skills: [], templates: [], ruleFiles: [] };
|
|
46
46
|
|
|
47
47
|
// Navigation-style interaction: Enter to enter directory or install file
|
|
@@ -50,13 +50,13 @@ async function promptSelections(inventory) {
|
|
|
50
50
|
while (true) {
|
|
51
51
|
const installedCount =
|
|
52
52
|
selections.ruleFiles.length + selections.skills.length + selections.templates.length;
|
|
53
|
-
const status = installedCount > 0 ? ` [${installedCount} items
|
|
53
|
+
const status = installedCount > 0 ? ` [${installedCount} items installed]` : "";
|
|
54
54
|
|
|
55
55
|
const mainChoices = [
|
|
56
56
|
{ title: "rules", value: "rules" },
|
|
57
57
|
{ title: "skills", value: "skills" },
|
|
58
58
|
{ title: "templates", value: "templates" },
|
|
59
|
-
{ title: `---
|
|
59
|
+
{ title: `--- Exit${status} ---`, value: "done" },
|
|
60
60
|
];
|
|
61
61
|
|
|
62
62
|
const mainResponse = await prompts({
|
|
@@ -71,18 +71,18 @@ async function promptSelections(inventory) {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
if (mainResponse.action === "rules") {
|
|
74
|
-
await navigateRules(inventory, selections);
|
|
74
|
+
await navigateRules(inventory, selections, targetRoot, options);
|
|
75
75
|
} else if (mainResponse.action === "skills") {
|
|
76
|
-
await navigateSkills(inventory, selections);
|
|
76
|
+
await navigateSkills(inventory, selections, targetRoot, options);
|
|
77
77
|
} else if (mainResponse.action === "templates") {
|
|
78
|
-
await navigateTemplates(inventory, selections);
|
|
78
|
+
await navigateTemplates(inventory, selections, targetRoot, options);
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
return selections;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
async function navigateRules(inventory, selections) {
|
|
85
|
+
async function navigateRules(inventory, selections, targetRoot, options) {
|
|
86
86
|
while (true) {
|
|
87
87
|
const domainChoices = inventory.domains.map((domain) => {
|
|
88
88
|
const selectedCount = selections.ruleFiles.filter(
|
|
@@ -112,11 +112,11 @@ async function navigateRules(inventory, selections) {
|
|
|
112
112
|
if (!domain) continue;
|
|
113
113
|
|
|
114
114
|
// Navigate into domain - show rules
|
|
115
|
-
await navigateDomainRules(domainName, domain, selections);
|
|
115
|
+
await navigateDomainRules(domainName, domain, selections, inventory, targetRoot, options);
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
async function navigateDomainRules(domainName, domain, selections) {
|
|
119
|
+
async function navigateDomainRules(domainName, domain, selections, inventory, targetRoot, options) {
|
|
120
120
|
while (true) {
|
|
121
121
|
const alreadySelected = new Set(
|
|
122
122
|
selections.ruleFiles
|
|
@@ -156,7 +156,9 @@ async function navigateDomainRules(domainName, domain, selections) {
|
|
|
156
156
|
if (!selections.domains.includes(domainName)) {
|
|
157
157
|
selections.domains.push(domainName);
|
|
158
158
|
}
|
|
159
|
-
|
|
159
|
+
|
|
160
|
+
// Install immediately
|
|
161
|
+
await installSingleRule(ruleEntry, inventory, targetRoot, options);
|
|
160
162
|
} else {
|
|
161
163
|
console.log(` Already installed: ${ruleEntry.file.name}`);
|
|
162
164
|
}
|
|
@@ -164,7 +166,28 @@ async function navigateDomainRules(domainName, domain, selections) {
|
|
|
164
166
|
}
|
|
165
167
|
}
|
|
166
168
|
|
|
167
|
-
async function
|
|
169
|
+
async function installSingleRule(ruleEntry, inventory, targetRoot, options) {
|
|
170
|
+
const item = {
|
|
171
|
+
sourcePath: ruleEntry.file.path,
|
|
172
|
+
targetPath: path.join(targetRoot, ".cursor", "rules", ruleEntry.file.name),
|
|
173
|
+
label: `rules:${ruleEntry.domain}`,
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const results = await executeCopyPlan({ items: [item] }, {
|
|
177
|
+
overwrite: Boolean(options.overwrite),
|
|
178
|
+
dryRun: Boolean(options.dryRun),
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
if (results.copied.length > 0) {
|
|
182
|
+
console.log(` ✓ Installed: ${ruleEntry.file.name}`);
|
|
183
|
+
} else if (results.conflicts.length > 0) {
|
|
184
|
+
console.log(` ⚠ Skipped (exists): ${ruleEntry.file.name} (use --overwrite to replace)`);
|
|
185
|
+
} else if (options.dryRun) {
|
|
186
|
+
console.log(` ✓ Would install: ${ruleEntry.file.name} (dry-run)`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async function navigateSkills(inventory, selections, targetRoot, options) {
|
|
168
191
|
while (true) {
|
|
169
192
|
const alreadySelected = new Set(selections.skills);
|
|
170
193
|
const skillChoices = inventory.skills.map((skill) => {
|
|
@@ -192,7 +215,7 @@ async function navigateSkills(inventory, selections) {
|
|
|
192
215
|
const index = selections.skills.indexOf(skillName);
|
|
193
216
|
if (index < 0) {
|
|
194
217
|
selections.skills.push(skillName);
|
|
195
|
-
|
|
218
|
+
await installSingleSkill(skillName, inventory, targetRoot, options);
|
|
196
219
|
} else {
|
|
197
220
|
console.log(` Already installed: ${skillName}`);
|
|
198
221
|
}
|
|
@@ -200,7 +223,26 @@ async function navigateSkills(inventory, selections) {
|
|
|
200
223
|
}
|
|
201
224
|
}
|
|
202
225
|
|
|
203
|
-
async function
|
|
226
|
+
async function installSingleSkill(skillName, inventory, targetRoot, options) {
|
|
227
|
+
const skill = inventory.skills.find((s) => s.name === skillName);
|
|
228
|
+
if (!skill) return;
|
|
229
|
+
|
|
230
|
+
const items = await collectSkillItems(inventory.skillsRoot, skillName, targetRoot);
|
|
231
|
+
const results = await executeCopyPlan({ items }, {
|
|
232
|
+
overwrite: Boolean(options.overwrite),
|
|
233
|
+
dryRun: Boolean(options.dryRun),
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
if (results.copied.length > 0) {
|
|
237
|
+
console.log(` ✓ Installed: ${skillName} (${results.copied.length} files)`);
|
|
238
|
+
} else if (results.conflicts.length > 0) {
|
|
239
|
+
console.log(` ⚠ Skipped (exists): ${skillName} (use --overwrite to replace)`);
|
|
240
|
+
} else if (options.dryRun) {
|
|
241
|
+
console.log(` ✓ Would install: ${skillName} (${items.length} files, dry-run)`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async function navigateTemplates(inventory, selections, targetRoot, options) {
|
|
204
246
|
while (true) {
|
|
205
247
|
const alreadySelected = new Set(selections.templates);
|
|
206
248
|
const templateChoices = inventory.templates.map((template) => {
|
|
@@ -228,7 +270,7 @@ async function navigateTemplates(inventory, selections) {
|
|
|
228
270
|
const index = selections.templates.indexOf(templateName);
|
|
229
271
|
if (index < 0) {
|
|
230
272
|
selections.templates.push(templateName);
|
|
231
|
-
|
|
273
|
+
await installSingleTemplate(templateName, inventory, targetRoot, options);
|
|
232
274
|
} else {
|
|
233
275
|
console.log(` Already installed: ${templateName}`);
|
|
234
276
|
}
|
|
@@ -236,6 +278,25 @@ async function navigateTemplates(inventory, selections) {
|
|
|
236
278
|
}
|
|
237
279
|
}
|
|
238
280
|
|
|
281
|
+
async function installSingleTemplate(templateName, inventory, targetRoot, options) {
|
|
282
|
+
const template = inventory.templates.find((t) => t.name === templateName);
|
|
283
|
+
if (!template) return;
|
|
284
|
+
|
|
285
|
+
const items = await collectTemplateItems(inventory.templatesRoot, templateName, targetRoot);
|
|
286
|
+
const results = await executeCopyPlan({ items }, {
|
|
287
|
+
overwrite: Boolean(options.overwrite),
|
|
288
|
+
dryRun: Boolean(options.dryRun),
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
if (results.copied.length > 0) {
|
|
292
|
+
console.log(` ✓ Installed: ${templateName}`);
|
|
293
|
+
} else if (results.conflicts.length > 0) {
|
|
294
|
+
console.log(` ⚠ Skipped (exists): ${templateName} (use --overwrite to replace)`);
|
|
295
|
+
} else if (options.dryRun) {
|
|
296
|
+
console.log(` ✓ Would install: ${templateName} (dry-run)`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
239
300
|
function summarizeSelections(plan) {
|
|
240
301
|
return {
|
|
241
302
|
domains: plan.selectedDomains,
|
|
@@ -254,18 +315,42 @@ async function runInstall(options) {
|
|
|
254
315
|
options.target || (config && config.targetPath) || "."
|
|
255
316
|
);
|
|
256
317
|
|
|
257
|
-
|
|
258
|
-
|
|
318
|
+
let selections;
|
|
319
|
+
let plan;
|
|
320
|
+
let results;
|
|
321
|
+
|
|
322
|
+
if (config) {
|
|
323
|
+
// Config mode: install all at once
|
|
324
|
+
selections = config;
|
|
325
|
+
plan = await buildCopyPlan(inventory, selections, targetRoot);
|
|
326
|
+
results = await executeCopyPlan(plan, {
|
|
327
|
+
overwrite: Boolean(options.overwrite),
|
|
328
|
+
dryRun: Boolean(options.dryRun),
|
|
329
|
+
});
|
|
330
|
+
} else {
|
|
331
|
+
// Interactive mode: install immediately on selection
|
|
332
|
+
selections = await promptSelections(inventory, targetRoot, options) || {
|
|
259
333
|
domains: [],
|
|
260
334
|
skills: [],
|
|
261
335
|
templates: [],
|
|
262
336
|
};
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
337
|
+
// In interactive mode, files are already installed during selection
|
|
338
|
+
// Just show summary without re-installing
|
|
339
|
+
const totalInstalled =
|
|
340
|
+
selections.ruleFiles.length +
|
|
341
|
+
selections.skills.length +
|
|
342
|
+
selections.templates.length;
|
|
343
|
+
results = {
|
|
344
|
+
copied: totalInstalled,
|
|
345
|
+
conflicts: 0,
|
|
346
|
+
skipped: 0,
|
|
347
|
+
};
|
|
348
|
+
plan = {
|
|
349
|
+
selectedDomains: selections.domains,
|
|
350
|
+
selectedSkills: selections.skills,
|
|
351
|
+
selectedTemplates: selections.templates,
|
|
352
|
+
};
|
|
353
|
+
}
|
|
269
354
|
|
|
270
355
|
if (options.json) {
|
|
271
356
|
console.log(
|
package/src/install.js
CHANGED
|
@@ -186,6 +186,8 @@ async function executeCopyPlan(plan, { overwrite, dryRun }) {
|
|
|
186
186
|
module.exports = {
|
|
187
187
|
buildCopyPlan,
|
|
188
188
|
executeCopyPlan,
|
|
189
|
+
collectSkillItems,
|
|
190
|
+
collectTemplateItems,
|
|
189
191
|
normalizeDomainsSelection,
|
|
190
192
|
normalizeSkillsSelection,
|
|
191
193
|
normalizeTemplatesSelection,
|