accio-context 1.0.0 → 1.0.2

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": "accio-context",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "CLI tool to install Accio context assets (rules, skills, templates) into projects",
5
5
  "main": "src/cli.js",
6
6
  "type": "commonjs",
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 ready]` : "";
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: `--- Complete and install${status} ---`, value: "done" },
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
- console.log(` ✓ Installed: ${ruleEntry.file.name}`);
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 navigateSkills(inventory, selections) {
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
- console.log(` ✓ Installed: ${skillName}`);
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 navigateTemplates(inventory, selections) {
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
- console.log(` ✓ Installed: ${templateName}`);
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
- const selections =
258
- config || (await promptSelections(inventory)) || {
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
- const plan = await buildCopyPlan(inventory, selections, targetRoot);
265
- const results = await executeCopyPlan(plan, {
266
- overwrite: Boolean(options.overwrite),
267
- dryRun: Boolean(options.dryRun),
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,