auriga-cli 1.25.0 → 1.26.0

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/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ import { exec, fetchContentRoot, getPackageRoot, isNonInteractive, LANGUAGES, lo
6
6
  import { installWorkflow } from "./workflow.js";
7
7
  import { installSkills, installRecommendedSkills } from "./skills.js";
8
8
  import { installPlugins } from "./plugins.js";
9
- import { installHooks } from "./hooks.js";
9
+ import { installPreset } from "./preset.js";
10
10
  import { loadCatalog } from "./catalog.js";
11
11
  import { renderHelp, renderTypeHelp } from "./help.js";
12
12
  import { renderGuide } from "./guide.js";
@@ -17,7 +17,6 @@ const TYPE_FOR_FILTER = {
17
17
  "--skill": "skills",
18
18
  "--recommended-skill": "recommended",
19
19
  "--plugin": "plugins",
20
- "--hook": "hooks",
21
20
  };
22
21
  function parseErr(msg) {
23
22
  throw new Error(msg);
@@ -179,6 +178,18 @@ function parseInstall(argv) {
179
178
  i += 1;
180
179
  continue;
181
180
  }
181
+ // `--preset` is a boolean flag — it takes no value. Reject the
182
+ // `--preset=...` equals form explicitly rather than letting it fall
183
+ // through to the generic "unknown argument" branch, so the user gets
184
+ // a message that names the actual mistake.
185
+ if (t === "--preset") {
186
+ out.preset = true;
187
+ i += 1;
188
+ continue;
189
+ }
190
+ if (t.startsWith("--preset=")) {
191
+ parseErr("--preset takes no value.");
192
+ }
182
193
  // Accept both `--lang en` and `--lang=en` (and same for --cwd, --scope).
183
194
  // The equals form is a common CLI affordance; rejecting it confuses
184
195
  // users with any prior gnu-style / node util.parseArgs experience.
@@ -244,6 +255,37 @@ function parseInstall(argv) {
244
255
  return out;
245
256
  }
246
257
  function validateInstall(out, filterFlag) {
258
+ // Rule 1: --preset is atomic. It installs the curated default set
259
+ // (workflow doc + workflow skills + auriga-workflow plugin) and cannot
260
+ // combine with a <type>, a sub-item filter, or --all. Unlike a category
261
+ // install it DOES accept --scope / --agent / --lang as preset modifiers
262
+ // (the preset defaults differ: user / both / en). --cwd is not a preset
263
+ // modifier — the workflow doc always lands in the current directory.
264
+ if (out.preset) {
265
+ if (out.all) {
266
+ parseErr("--preset and --all are both atomic; pass only one.");
267
+ }
268
+ if (out.type) {
269
+ parseErr(`--preset is atomic; it cannot combine with the '${out.type}' type.`);
270
+ }
271
+ if (out.filter) {
272
+ parseErr("--preset is atomic; it cannot combine with --skill/--recommended-skill/--plugin.");
273
+ }
274
+ if (out.cwd !== undefined) {
275
+ parseErr("--cwd does not apply to --preset.");
276
+ }
277
+ if (out.scope !== undefined)
278
+ validateScopeValue(out.scope);
279
+ if (out.agent !== undefined)
280
+ validateAgentValue(out.agent);
281
+ if (out.lang !== undefined) {
282
+ const valid = LANGUAGES.map((l) => l.value);
283
+ if (!valid.includes(out.lang)) {
284
+ parseErr(`unknown language '${out.lang}'; available: ${valid.join(", ")}`);
285
+ }
286
+ }
287
+ return;
288
+ }
247
289
  // Rule 2: --all is atomic.
248
290
  if (out.all) {
249
291
  if (out.type || out.filter || out.lang !== undefined || out.cwd !== undefined) {
@@ -267,7 +309,7 @@ function validateInstall(out, filterFlag) {
267
309
  if ((out.lang !== undefined || out.cwd !== undefined) && out.type !== "workflow") {
268
310
  parseErr("--lang/--cwd only apply to workflow.");
269
311
  }
270
- // Rule 6: --scope only for skills / recommended / plugins / hooks.
312
+ // Rule 6: --scope only for skills / recommended / plugins.
271
313
  // workflow (single file + symlink) has no scope concept.
272
314
  if (out.scope !== undefined) {
273
315
  if (out.type === "workflow") {
@@ -308,8 +350,7 @@ function validateFilterAgainstCatalog(type, filter) {
308
350
  const bucket = type === "skills" ? catalog.workflowSkills
309
351
  : type === "recommended" ? catalog.recommendedSkills
310
352
  : type === "plugins" ? catalog.plugins
311
- : type === "hooks" ? catalog.hooks
312
- : null;
353
+ : null;
313
354
  if (!bucket)
314
355
  return;
315
356
  const available = bucket.map((e) => e.name);
@@ -327,9 +368,6 @@ function migratedPluginHint(type, name) {
327
368
  ["incremental-impl", "test-designer", "session-compound"].includes(name)) {
328
369
  return "This skill moved to the auriga-workflow plugin; install it with `install plugins --plugin auriga-workflow`.";
329
370
  }
330
- if (type === "hooks" && name === "notify") {
331
- return "The notify hook moved to the auriga-notify plugin; install it with `install plugins --plugin auriga-notify`.";
332
- }
333
371
  return undefined;
334
372
  }
335
373
  function categorySingular(type) {
@@ -350,8 +388,16 @@ function validateAgentValue(agent) {
350
388
  // ---------------------------------------------------------------------------
351
389
  // main — returns exit code (spec §5.3.1 / §7)
352
390
  // ---------------------------------------------------------------------------
353
- // --all excludes `recommended` (per spec §3.2) they're opt-in utilities.
354
- const ALL_CATEGORIES = ["workflow", "skills", "plugins", "hooks"];
391
+ // --all is "install everything": every category, including the opt-in
392
+ // recommended skills. Order matches the menu / execution order
393
+ // (workflow → skills → recommended → plugins). The curated subset lives
394
+ // behind --preset (workflow doc + workflow skills + auriga-workflow).
395
+ const ALL_CATEGORIES = [
396
+ "workflow",
397
+ "skills",
398
+ "recommended",
399
+ "plugins",
400
+ ];
355
401
  export async function main(argv) {
356
402
  let parsed;
357
403
  try {
@@ -403,14 +449,19 @@ export async function main(argv) {
403
449
  return runInstall(parsed.install);
404
450
  }
405
451
  async function runInstall(p) {
406
- // Bare `install` (no type, no --all, no filter): TTY → menu, non-TTY → exit 1.
407
- if (!p.all && !p.type) {
452
+ // Bare `install` (no type, no --all, no --preset, no filter):
453
+ // TTY menu, non-TTY → exit 1.
454
+ if (!p.all && !p.preset && !p.type) {
408
455
  if (isNonInteractive()) {
409
456
  log.error("Interactive mode requires a TTY. Run 'npx auriga-cli --help' for non-interactive options.");
410
457
  return 1;
411
458
  }
412
459
  return runLegacyMenu();
413
460
  }
461
+ // --preset: curated default-set install (precheck + ordered fan-out).
462
+ if (p.preset) {
463
+ return runPreset(p);
464
+ }
414
465
  // --all: precheck + fan-out.
415
466
  if (p.all) {
416
467
  return runAll(p);
@@ -418,6 +469,50 @@ async function runInstall(p) {
418
469
  // Single-category install.
419
470
  return runSingle(p);
420
471
  }
472
+ /**
473
+ * `install --preset` — installs the curated default set via the shared
474
+ * `installPreset` orchestrator. Graded exit mirrors `runAll`: all steps
475
+ * succeed → 0; any step fails → 2 with per-step status on stderr.
476
+ *
477
+ * The preset defaults differ from a category install — scope=user,
478
+ * agent=both, lang=en — and are resolved here before handing off, so
479
+ * `installPreset` itself stays default-free (the TUI / Web UI callers
480
+ * resolve their own defaults the same way).
481
+ */
482
+ async function runPreset(p) {
483
+ const agent = p.agent ?? "both";
484
+ const prep = await prepareInstall(["plugins"], agent);
485
+ if ("exit" in prep)
486
+ return prep.exit;
487
+ const { packageRoot } = prep;
488
+ const results = await installPreset(packageRoot, {
489
+ interactive: false,
490
+ scope: p.scope ?? "user",
491
+ agent,
492
+ lang: p.lang ?? "en",
493
+ });
494
+ for (const r of results) {
495
+ if (r.ok) {
496
+ process.stderr.write(`[OK] ${r.category}\n`);
497
+ }
498
+ else {
499
+ process.stderr.write(`[FAIL] ${r.category} — ${r.err}\n`);
500
+ }
501
+ }
502
+ const failed = results.filter((r) => !r.ok);
503
+ if (failed.length === 0) {
504
+ process.stderr.write(RELOAD_REMINDER);
505
+ return 0;
506
+ }
507
+ // The preset is one atomic "install the right defaults" action — the
508
+ // retry is the whole command again, not a per-category fan-out like
509
+ // runAll's hint.
510
+ process.stderr.write("\nRetry:\n npx -y auriga-cli install --preset\n");
511
+ if (failed.length < results.length) {
512
+ process.stderr.write(RELOAD_REMINDER);
513
+ }
514
+ return 2;
515
+ }
421
516
  /**
422
517
  * Precheck external prerequisites before touching any files.
423
518
  * Returns null if OK, or an error message.
@@ -481,7 +576,7 @@ async function runAll(p) {
481
576
  for (const category of ALL_CATEGORIES) {
482
577
  // Forward `scope` only when the user actually passed one. Each
483
578
  // installer picks its own default for undefined so category-specific
484
- // defaults (skills/recommended/plugins/hooks all map undefined → project)
579
+ // defaults (skills/recommended/plugins all map undefined → project)
485
580
  // aren't flattened by a one-size-fits-all fallback here.
486
581
  const opts = {
487
582
  interactive: false,
@@ -566,7 +661,6 @@ async function dispatchInstaller(category, packageRoot, opts) {
566
661
  case "skills": return installSkills(packageRoot, opts);
567
662
  case "recommended": return installRecommendedSkills(packageRoot, opts);
568
663
  case "plugins": return installPlugins(packageRoot, opts);
569
- case "hooks": return installHooks(packageRoot, opts);
570
664
  }
571
665
  }
572
666
  // ---------------------------------------------------------------------------
@@ -664,7 +758,9 @@ async function runUi(p, version) {
664
758
  skill: new Set(Object.keys(scanCatalog.skills)),
665
759
  "recommended-skill": new Set(Object.keys(scanCatalog.recommendedSkills)),
666
760
  plugin: new Set(Object.keys(scanCatalog.plugins)),
667
- hook: new Set(Object.keys(scanCatalog.hooks)),
761
+ // Preset is a singleton apply target — the sentinel name "preset"
762
+ // matches what the Dashboard's preset button sends.
763
+ preset: new Set(["preset"]),
668
764
  };
669
765
  const pluginAgentsByName = new Map();
670
766
  for (const [name, def] of Object.entries(scanCatalog.plugins)) {
@@ -775,10 +871,33 @@ function highlight(text) {
775
871
  return text;
776
872
  return `\x1b[1;36m${text}\x1b[0m`;
777
873
  }
778
- // ---------------------------------------------------------------------------
779
- // Legacy checkbox menu preserved for `npx auriga-cli install` in TTY
780
- // and `npx auriga-cli` with no args.
781
- // ---------------------------------------------------------------------------
874
+ /**
875
+ * The TUI's three menu items, in fixed order. Lifted to a module-level
876
+ * constant so VAL-TUI-001 / VAL-TUI-002 can assert the "exactly 3 items /
877
+ * order / default-checked" contract without driving inquirer.
878
+ *
879
+ * Workflow + Skills are absorbed by the「推荐预设」item.
880
+ * The preset label spells out the silent defaults (scope user / agent
881
+ * both / lang en) so a TTY user knows what they're getting — fine-tuning
882
+ * those goes through the non-interactive `install --preset` flags.
883
+ */
884
+ export const LEGACY_MENU_CHOICES = [
885
+ {
886
+ value: "preset",
887
+ name: "Recommended preset — CLAUDE.md/AGENTS.md + workflow skills + auriga-workflow plugin (scope user · agent both · lang en)",
888
+ checked: true,
889
+ },
890
+ {
891
+ value: "recommended",
892
+ name: "Optional skills — opt-in utility skills (claude-code-agent, codex-agent...)",
893
+ checked: false,
894
+ },
895
+ {
896
+ value: "plugins",
897
+ name: "Other plugins — everything except auriga-workflow (auriga-notify, skill-creator, codex...)",
898
+ checked: false,
899
+ },
900
+ ];
782
901
  async function runLegacyMenu() {
783
902
  // Lazy-load TTY-only deps so the non-interactive code path doesn't
784
903
  // force inquirer / printBanner / withEsc into the module graph.
@@ -796,40 +915,42 @@ async function runLegacyMenu() {
796
915
  const packageRoot = await fetchContentRoot();
797
916
  if (process.env.DEV !== "1")
798
917
  console.log("");
799
- const moduleTypes = await withEsc(checkbox({
800
- message: "Select module types to install:",
801
- choices: [
802
- { name: "Workflow — CLAUDE.md + AGENTS.md", value: "workflow", checked: true },
803
- { name: "Skills — Development process skills (TDD, debugging, verification, planning...)", value: "skills", checked: true },
804
- { name: "Recommended Skills — Extra utility skills (claude-code-agent, codex-agent...)", value: "recommended", checked: true },
805
- { name: "Plugins — Claude Code / Codex plugins (skill-creator, codex, auriga-workflow...)", value: "plugins", checked: true },
806
- { name: "Hooks — Claude Code hooks (notifications, etc.)", value: "hooks", checked: true },
807
- ],
918
+ const picks = await withEsc(checkbox({
919
+ message: "Select what to install:",
920
+ choices: LEGACY_MENU_CHOICES.map((c) => ({
921
+ name: c.name,
922
+ value: c.value,
923
+ checked: c.checked,
924
+ })),
808
925
  }));
809
- if (moduleTypes.length === 0) {
926
+ if (picks.length === 0) {
810
927
  console.log("Nothing selected. Bye!");
811
928
  return 0;
812
929
  }
813
- const interactiveOpts = { interactive: true };
814
- if (moduleTypes.includes("workflow")) {
815
- console.log("\n--- Workflow ---\n");
816
- await installWorkflow(packageRoot, interactiveOpts);
817
- }
818
- if (moduleTypes.includes("skills")) {
819
- console.log("\n--- Skills ---\n");
820
- await installSkills(packageRoot, interactiveOpts);
821
- }
822
- if (moduleTypes.includes("recommended")) {
823
- console.log("\n--- Recommended Skills ---\n");
824
- await installRecommendedSkills(packageRoot, interactiveOpts);
825
- }
826
- if (moduleTypes.includes("plugins")) {
827
- console.log("\n--- Plugins ---\n");
828
- await installPlugins(packageRoot, interactiveOpts);
930
+ // 「推荐预设」silently uses the preset defaults (scope user / agent
931
+ // both / lang en) — it does not prompt for them. The other two items
932
+ // drill down into their category's per-item sub-selection as before.
933
+ if (picks.includes("preset")) {
934
+ console.log("\n--- Recommended preset ---\n");
935
+ await installPreset(packageRoot, {
936
+ interactive: true,
937
+ scope: "user",
938
+ agent: "both",
939
+ lang: "en",
940
+ });
829
941
  }
830
- if (moduleTypes.includes("hooks")) {
831
- console.log("\n--- Hooks ---\n");
832
- await installHooks(packageRoot, interactiveOpts);
942
+ if (picks.includes("recommended")) {
943
+ console.log("\n--- Optional skills ---\n");
944
+ await installRecommendedSkills(packageRoot, { interactive: true });
945
+ }
946
+ if (picks.includes("plugins")) {
947
+ console.log("\n--- Other plugins ---\n");
948
+ await installPlugins(packageRoot, {
949
+ interactive: true,
950
+ // auriga-workflow is already covered by the preset — keep it out
951
+ // of this sub-selection (VAL-TUI-005).
952
+ excludePlugins: ["auriga-workflow"],
953
+ });
833
954
  }
834
955
  console.log("\n✨ Installation complete!\n");
835
956
  return 0;
package/dist/guide.js CHANGED
@@ -20,7 +20,7 @@ export function renderGuide(opts) {
20
20
  return `${h(`# auriga-cli bootstrap SOP (v${opts.version})`)}
21
21
 
22
22
  This guide walks an Agent through installing the auriga harness
23
- (CLAUDE.md + skills + plugins, plus any legacy hooks) into the current repository.
23
+ (CLAUDE.md + skills + plugins) into the current repository.
24
24
 
25
25
  Run each step in order. If any step fails with exit 1, stop and report.
26
26
  If exit 2, see stderr for per-category status and follow the "Retry"
@@ -44,13 +44,13 @@ If you plan to install Codex plugins, also verify \`codex --version\`.
44
44
 
45
45
  ${h("## Step 2 — Read --help BEFORE installing (do not skip)")}
46
46
 
47
- ${warn("⚠")} Always inspect the catalog first so you know which skills,
48
- plugins, and hooks are actually relevant for this project. Blindly
49
- running \`install --all\` works as a turnkey preset, but for anything
50
- beyond a greenfield bootstrap you should narrow scope.
47
+ ${warn("⚠")} Always inspect the catalog first so you know which skills
48
+ and plugins are actually relevant for this project. Blindly
49
+ running \`install --preset\` works as a turnkey bootstrap, but for
50
+ anything beyond a greenfield setup you should narrow scope.
51
51
 
52
- Top-level catalog (every workflow skill / recommended skill / plugin /
53
- hook with a short description):
52
+ Top-level catalog (every workflow skill / recommended skill / plugin
53
+ with a short description):
54
54
  ${cmd("npx -y auriga-cli --help")}
55
55
 
56
56
  Per-type detail (flags + only that category's catalog slice):
@@ -58,12 +58,15 @@ Per-type detail (flags + only that category's catalog slice):
58
58
  ${cmd("npx -y auriga-cli install skills --help")}
59
59
  ${cmd("npx -y auriga-cli install recommended --help")}
60
60
  ${cmd("npx -y auriga-cli install plugins --help")}
61
- ${cmd("npx -y auriga-cli install hooks --help")}
62
61
 
63
62
  ${h("## Step 3 — Install")}
64
63
 
65
- Preset — the full default-on set (workflow + skills + default plugins;
66
- the legacy hooks category is currently empty; recommended skills are NOT included):
64
+ Recommended — the curated workflow preset (CLAUDE.md/AGENTS.md +
65
+ workflow skills + the auriga-workflow plugin). Defaults: scope user,
66
+ agent both (Claude Code + Codex), lang en:
67
+ ${cmd("npx -y auriga-cli install --preset")}
68
+
69
+ Everything — workflow + skills + recommended skills + default plugins:
67
70
  ${cmd("npx -y auriga-cli install --all")}
68
71
 
69
72
  Targeted — single category, picking from the catalog surfaced in Step 2:
@@ -93,7 +96,7 @@ Exit codes:
93
96
 
94
97
  ${h("## Step 4 — Reload session (REQUIRED when installed non-interactively)")}
95
98
 
96
- ${warn("⚠")} CLAUDE.md, .agents/skills/, plugin enablement, and hook/plugin
99
+ ${warn("⚠")} CLAUDE.md, .agents/skills/, and plugin enablement /
97
100
  registrations are loaded at session startup. If you ran
98
101
  \`npx -y auriga-cli install\` inside an existing Claude Code or Codex session
99
102
  (e.g., \`claude -p\` / \`claude -p --worktree\` / \`codex exec\`), the current session
@@ -112,7 +115,7 @@ Expected artifacts/checks:
112
115
  - .agents/skills/<name>/ (one per installed skill)
113
116
  - claude plugins list (shows Claude plugins, if Claude plugins selected)
114
117
  - ~/.codex/config.toml (Codex plugin enablement, if Codex plugins selected)
115
- - .claude/settings.json (updated hook/plugin registrations, if selected)
118
+ - .claude/settings.json (updated plugin registrations, if selected)
116
119
  - .claude/auriga-notify/ (project notify config, if auriga-notify selected)
117
120
 
118
121
  ${h("## Troubleshooting")}
package/dist/help.js CHANGED
@@ -10,9 +10,13 @@ export function renderHelp(catalog, version) {
10
10
  USAGE
11
11
  npx auriga-cli guide Agent bootstrap SOP (start here)
12
12
  npx auriga-cli install (TTY only) checkbox menu
13
+ npx auriga-cli install --preset [--scope <s>] [--agent <a>] [--lang <code>]
14
+ curated default set: workflow doc
15
+ + workflow skills + auriga-workflow plugin
16
+ (defaults: scope user, agent both, lang en)
13
17
  npx auriga-cli install --all [--scope <s>] [--agent <a>]
14
- workflow + skills + plugins + hooks
15
- (excludes recommended install separately)
18
+ everything: workflow + skills
19
+ + recommended + plugins
16
20
  npx auriga-cli install <type> [type-specific flags] single category
17
21
  npx auriga-cli install <type> --help per-category help + catalog subset
18
22
  npx auriga-cli web-ui [--port <n>] [--ui-dir <path>] [--no-open]
@@ -21,14 +25,13 @@ USAGE
21
25
 
22
26
  For non-interactive (Agent) use, prepend npx's own -y flag:
23
27
  npx -y auriga-cli guide
24
- npx -y auriga-cli install --all
28
+ npx -y auriga-cli install --preset
25
29
 
26
30
  TYPES (exactly one with <type> form)
27
31
  workflow CLAUDE.md + AGENTS.md (workflow manifesto)
28
32
  skills Default-on workflow skills (listed below)
29
33
  recommended Opt-in utility skills (listed below)
30
34
  plugins Claude Code and Codex plugins (listed below)
31
- hooks Project-level hooks for Claude Code (listed below)
32
35
 
33
36
  TYPE-SPECIFIC FLAGS
34
37
  workflow: --lang <code> default en; available: en, zh-CN
@@ -40,9 +43,6 @@ TYPE-SPECIFIC FLAGS
40
43
  plugins: --plugin <names...>
41
44
  --agent <claude|codex|both> default claude
42
45
  --scope <project|user> default project
43
- hooks: --hook <names...> non-interactive default installs every
44
- hook with defaultOn != false
45
- --scope <project|user> default project
46
46
 
47
47
  TOP-LEVEL OPTIONS
48
48
  -h, --help show this help
@@ -52,18 +52,15 @@ TOP-LEVEL OPTIONS
52
52
  CATALOG (what each category contains)
53
53
  ──────────────────────────────────────────────────────
54
54
 
55
- Workflow skills (category: skills) ← installed by --all
55
+ Workflow skills (category: skills) ← installed by --all and --preset
56
56
  ${col(catalog.workflowSkills)}
57
57
 
58
- Recommended skills (category: recommended) ← NOT installed by --all
58
+ Recommended skills (category: recommended) ← installed by --all, NOT by --preset
59
59
  ${col(catalog.recommendedSkills)}
60
60
 
61
61
  Plugins (category: plugins)
62
62
  ${col(catalog.plugins)}
63
63
 
64
- Hooks (category: hooks)
65
- ${col(catalog.hooks)}
66
-
67
64
  More: https://github.com/Ben2pc/auriga-cli
68
65
  `;
69
66
  }
@@ -114,7 +111,7 @@ FLAGS
114
111
  omit → install every recommended skill listed below
115
112
  --scope <project|user> default project
116
113
 
117
- CATALOG (recommended skills — opt-in, NOT installed by --all)
114
+ CATALOG (recommended skills — opt-in; installed by --all, not by --preset)
118
115
  ${col(catalog.recommendedSkills)}
119
116
  `;
120
117
  case "plugins":
@@ -133,21 +130,6 @@ FLAGS
133
130
 
134
131
  CATALOG (plugins)
135
132
  ${col(catalog.plugins)}
136
- `;
137
- case "hooks":
138
- return `${header}
139
-
140
- USAGE
141
- npx auriga-cli install hooks [--hook <names...>] [--scope <project|user>]
142
-
143
- FLAGS
144
- --hook <names...> space-separated; '*' = every compatible hook
145
- omit → install every hook with defaultOn != false
146
- --scope <project|user> default project
147
- (project-local is only reachable via the TTY menu)
148
-
149
- CATALOG (hooks — entries flagged "(opt-in)" require explicit --hook)
150
- ${col(catalog.hooks)}
151
133
  `;
152
134
  }
153
135
  }
package/dist/plugins.d.ts CHANGED
@@ -27,6 +27,15 @@ export interface ExtraPluginConfigs {
27
27
  plugins: ExtraPluginConfig[];
28
28
  }
29
29
  export declare function validateExtraPluginConfigs(raw: unknown): asserts raw is ExtraPluginConfigs;
30
+ /**
31
+ * Drops `exclude`-named plugins from a candidate list. The TUI's
32
+ *「其他插件」menu item passes `["auriga-workflow"]` so the plugin already
33
+ * installed by the preset isn't offered again (VAL-TUI-005). A pure,
34
+ * order-preserving filter — `undefined` / empty `exclude` is a no-op.
35
+ */
36
+ export declare function excludeByName<T extends {
37
+ name: string;
38
+ }>(plugins: T[], exclude: readonly string[] | undefined): T[];
30
39
  export declare function loadExtraPluginConfigs(packageRoot: string): ExtraPluginConfigs;
31
40
  export declare function extraAppliesTo(extra: ExtraPluginConfig, runtime: PluginRuntime): boolean;
32
41
  export declare function extraByNameForRuntime(extras: ExtraPluginConfigs, runtime: PluginRuntime): Map<string, ExtraPluginConfig>;
package/dist/plugins.js CHANGED
@@ -114,6 +114,18 @@ function getInstalledPlugins(cwd = process.cwd()) {
114
114
  return new Map();
115
115
  }
116
116
  }
117
+ /**
118
+ * Drops `exclude`-named plugins from a candidate list. The TUI's
119
+ *「其他插件」menu item passes `["auriga-workflow"]` so the plugin already
120
+ * installed by the preset isn't offered again (VAL-TUI-005). A pure,
121
+ * order-preserving filter — `undefined` / empty `exclude` is a no-op.
122
+ */
123
+ export function excludeByName(plugins, exclude) {
124
+ if (!exclude || exclude.length === 0)
125
+ return plugins;
126
+ const drop = new Set(exclude);
127
+ return plugins.filter((p) => !drop.has(p.name));
128
+ }
117
129
  /**
118
130
  * Non-interactive selection resolver for plugins.
119
131
  * `undefined` = default-on set; `["*"]` = full set; explicit names =
@@ -727,16 +739,19 @@ async function installCodexPlugins(packageRoot, opts) {
727
739
  log.warn(msg);
728
740
  return;
729
741
  }
742
+ // `excludePlugins` (set by the TUI's「其他插件」item) keeps preset-owned
743
+ // plugins out of the offered set.
744
+ const offered = excludeByName(installConfig.plugins, opts.excludePlugins);
730
745
  const selected = opts.interactive
731
746
  ? await withEsc(checkbox({
732
747
  message: "Select Codex plugins to install:",
733
- choices: installConfig.plugins.map((p) => ({
748
+ choices: offered.map((p) => ({
734
749
  name: p.description ? `${p.name} — ${p.description}` : p.name,
735
750
  value: p,
736
751
  checked: p.defaultOn !== false,
737
752
  })),
738
753
  }))
739
- : resolveCodexPluginSelection(installConfig.plugins, opts.selected);
754
+ : resolveCodexPluginSelection(offered, opts.selected);
740
755
  if (selected.length === 0) {
741
756
  log.skip("No Codex plugins selected");
742
757
  return;
@@ -878,6 +893,9 @@ export async function installPlugins(packageRoot, opts) {
878
893
  }))
879
894
  : opts.scope ?? "project";
880
895
  if (config) {
896
+ // `excludePlugins` (set by the TUI's「其他插件」item) keeps
897
+ // preset-owned plugins out of the offered set.
898
+ config = { ...config, plugins: excludeByName(config.plugins, opts.excludePlugins) };
881
899
  const targetCwd = installTargetCwd(opts);
882
900
  const installed = getInstalledPlugins(targetCwd);
883
901
  let selected;
@@ -0,0 +1,38 @@
1
+ import type { PluginAgent } from "./utils.js";
2
+ /**
3
+ * 预设安装的插件成员 —— 固定只装 auriga-workflow。
4
+ * installPlugins 的 `selected` 过滤把安装面收敛到这一个插件。
5
+ * `as const` 冻结这个「单一真相」常量,调用方无法 .push() 篡改它。
6
+ */
7
+ export declare const PRESET_PLUGINS: readonly ["auriga-workflow"];
8
+ /**
9
+ * installPreset 的输入。三个默认值(scope=user / agent=both / lang=en)
10
+ * 与分类安装不同,由调用方负责落定后再传入 —— 预设的默认不在本函数内
11
+ * 兜底,使「默认值是什么」对每个调用端都显式可见。
12
+ */
13
+ export interface PresetOpts {
14
+ scope: "project" | "user";
15
+ agent: PluginAgent;
16
+ lang: string;
17
+ /** workflow 文档的安装目标目录;缺省即 installer 自身的 cwd 默认。 */
18
+ cwd?: string;
19
+ /** false = 非交互(CLI / Web UI),installer 在失败处抛错;
20
+ * true = 交互(TUI),installer log-and-continue。 */
21
+ interactive: boolean;
22
+ /** 逐行进度回调 —— Web UI 的 SSE 流式输出用。 */
23
+ onLog?: (line: string, stream: "stdout" | "stderr") => void;
24
+ }
25
+ /** 预设安装中单个步骤的成败。 */
26
+ export interface PresetStepResult {
27
+ category: "workflow" | "skills" | "plugins";
28
+ ok: boolean;
29
+ /** ok === false 时携带失败原因。 */
30
+ err?: string;
31
+ }
32
+ /**
33
+ * 按 workflow → skills → plugins 顺序执行预设安装。
34
+ *
35
+ * 每一步独立 try/catch:一步失败不阻断后续步骤(与 runAll 的
36
+ * log-and-continue 一致),逐步成败汇总后返回给调用方。
37
+ */
38
+ export declare function installPreset(packageRoot: string, opts: PresetOpts): Promise<PresetStepResult[]>;