auriga-cli 1.20.5 → 1.20.6
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/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/catalog.json +1 -1
- package/dist/plugins.js +81 -35
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -119,7 +119,7 @@ Supports both project and global installation scopes.
|
|
|
119
119
|
|
|
120
120
|
### Plugins
|
|
121
121
|
|
|
122
|
-
Installs selected plugins for Claude Code, Codex, or both. Claude Code uses `claude plugins install` and honors `--scope project|user`; Codex uses `codex plugin marketplace add` and enables selected plugins in `~/.codex/config.toml`.
|
|
122
|
+
Installs selected plugins for Claude Code, Codex, or both. Claude Code uses `claude plugins install` and honors `--scope project|user`; Codex uses `codex plugin marketplace add/upgrade` (the right one is picked by reading `~/.codex/config.toml`) and enables selected plugins in `~/.codex/config.toml`.
|
|
123
123
|
|
|
124
124
|
Examples:
|
|
125
125
|
|
package/README.zh-CN.md
CHANGED
|
@@ -119,7 +119,7 @@ npx auriga-cli
|
|
|
119
119
|
|
|
120
120
|
### Plugins
|
|
121
121
|
|
|
122
|
-
可以把选中的插件安装到 Claude Code、Codex 或两者都装。Claude Code 路径使用 `claude plugins install`,并遵守 `--scope project|user`;Codex
|
|
122
|
+
可以把选中的插件安装到 Claude Code、Codex 或两者都装。Claude Code 路径使用 `claude plugins install`,并遵守 `--scope project|user`;Codex 路径根据 `~/.codex/config.toml` 中是否已注册同名 marketplace 自动选择 `codex plugin marketplace add` 或 `upgrade`,并在 `~/.codex/config.toml` 里启用选中的插件。
|
|
123
123
|
|
|
124
124
|
示例:
|
|
125
125
|
|
package/dist/catalog.json
CHANGED
package/dist/plugins.js
CHANGED
|
@@ -422,18 +422,30 @@ function runPostInstallMigration(pluginName, opts, runtimes) {
|
|
|
422
422
|
migrateLegacyNotifyConfig(opts);
|
|
423
423
|
}
|
|
424
424
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
425
|
+
// Source string Codex CLI records in `~/.codex/config.toml`
|
|
426
|
+
// `[marketplaces.<name>].source` after `marketplace add` succeeds. Used for
|
|
427
|
+
// exact-string compare against the registered marketplace's source to detect
|
|
428
|
+
// same-name-different-source hijack attempts before running `upgrade`.
|
|
429
|
+
function codexLocalMarketplaceSource(packageRoot) {
|
|
430
|
+
if (process.env.DEV === "1")
|
|
431
|
+
return packageRoot;
|
|
432
|
+
return "https://github.com/Ben2pc/auriga-cli.git";
|
|
430
433
|
}
|
|
431
|
-
function
|
|
434
|
+
function codexExternalMarketplaceSource(source) {
|
|
432
435
|
// `source` is validated by validateExtraPluginConfigs against
|
|
433
436
|
// MARKETPLACE_SOURCE_RE (alphanumerics + `._/-`) — no shell metachars
|
|
434
|
-
// can reach this string.
|
|
435
|
-
|
|
436
|
-
|
|
437
|
+
// can reach this string.
|
|
438
|
+
return `https://github.com/${source}.git`;
|
|
439
|
+
}
|
|
440
|
+
function codexMarketplaceAddCommand(packageRoot) {
|
|
441
|
+
const source = codexLocalMarketplaceSource(packageRoot);
|
|
442
|
+
// DEV-mode local paths may contain spaces; URLs need no shell quoting.
|
|
443
|
+
return process.env.DEV === "1"
|
|
444
|
+
? `codex plugin marketplace add ${shellQuote(source)}`
|
|
445
|
+
: `codex plugin marketplace add ${source}`;
|
|
446
|
+
}
|
|
447
|
+
function codexExternalMarketplaceAddCommand(source) {
|
|
448
|
+
return `codex plugin marketplace add ${codexExternalMarketplaceSource(source)}`;
|
|
437
449
|
}
|
|
438
450
|
function codexMarketplaceUpgradeCommand(marketplaceName) {
|
|
439
451
|
return `codex plugin marketplace upgrade ${shellQuote(marketplaceName)}`;
|
|
@@ -449,13 +461,36 @@ function commandErrorText(error) {
|
|
|
449
461
|
parts.push(String(withOutput.stderr));
|
|
450
462
|
return parts.join("\n");
|
|
451
463
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
464
|
+
// Codex CLI records every added marketplace as `[marketplaces.<name>]` in
|
|
465
|
+
// `~/.codex/config.toml` with a `source` field. Returns that stored source
|
|
466
|
+
// for an exact-string compare against the source we would `add`, or null
|
|
467
|
+
// when the marketplace isn't registered or the entry is malformed.
|
|
468
|
+
//
|
|
469
|
+
// Why config.toml is the authoritative signal: Codex's `add` command is
|
|
470
|
+
// silently idempotent for an already-added marketplace (exit 0, prints to
|
|
471
|
+
// stdout, no error), so we can't detect already-added by catching an
|
|
472
|
+
// `add` failure. The stored source also lets us guard against same-name
|
|
473
|
+
// hijack — a fork registered under our marketplace name would be invisible
|
|
474
|
+
// to a presence-only check.
|
|
475
|
+
function readCodexMarketplaceSource(marketplaceName) {
|
|
476
|
+
const configPath = path.join(codexHome(), "config.toml");
|
|
477
|
+
if (!fs.existsSync(configPath))
|
|
478
|
+
return null;
|
|
479
|
+
try {
|
|
480
|
+
const parsed = parseToml(fs.readFileSync(configPath, "utf-8"));
|
|
481
|
+
const marketplaces = parsed.marketplaces;
|
|
482
|
+
if (typeof marketplaces !== "object" || marketplaces === null || Array.isArray(marketplaces)) {
|
|
483
|
+
return null;
|
|
484
|
+
}
|
|
485
|
+
const entry = marketplaces[marketplaceName];
|
|
486
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry))
|
|
487
|
+
return null;
|
|
488
|
+
const source = entry.source;
|
|
489
|
+
return typeof source === "string" ? source : null;
|
|
490
|
+
}
|
|
491
|
+
catch {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
459
494
|
}
|
|
460
495
|
function isCodexMarketplaceDifferentSource(error) {
|
|
461
496
|
return /already added from a different source/i.test(commandErrorText(error));
|
|
@@ -616,34 +651,45 @@ function enableCodexPluginConfig(configPath, pluginKeys, needsPluginHooks) {
|
|
|
616
651
|
const content = minimalContent ?? buildCodexPluginConfigToml(originalContent, configPath, pluginKeys, needsPluginHooks);
|
|
617
652
|
atomicWriteFile(configPath, content.endsWith("\n") ? content : `${content}\n`);
|
|
618
653
|
}
|
|
619
|
-
async function addCodexMarketplaceWithRetry(marketplaceName, addCommand, opts, marketplaceExecOpts, failures) {
|
|
654
|
+
async function addCodexMarketplaceWithRetry(marketplaceName, addCommand, expectedSource, opts, marketplaceExecOpts, failures) {
|
|
655
|
+
const registeredSource = readCodexMarketplaceSource(marketplaceName);
|
|
656
|
+
if (registeredSource !== null) {
|
|
657
|
+
if (registeredSource !== expectedSource) {
|
|
658
|
+
// Supply-chain guard: a same-name marketplace pointing at a different
|
|
659
|
+
// source (e.g. a fork URL) must not be silently `upgrade`d — its
|
|
660
|
+
// content would be cached under our name and consumed downstream.
|
|
661
|
+
const msg = `Codex marketplace ${marketplaceName} is already added from a different source`;
|
|
662
|
+
log.error(`${msg}\n registered: ${registeredSource}\n expected: ${expectedSource}`);
|
|
663
|
+
failures.push(msg);
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
try {
|
|
667
|
+
exec(codexMarketplaceUpgradeCommand(marketplaceName), marketplaceExecOpts);
|
|
668
|
+
log.ok(`Codex marketplace ${marketplaceName} upgraded`);
|
|
669
|
+
}
|
|
670
|
+
catch (e) {
|
|
671
|
+
// Surface the underlying upgrade error so a 6-month-out reader
|
|
672
|
+
// can tell apart ENOENT / network / auth / git failures.
|
|
673
|
+
log.error(`Failed to upgrade Codex marketplace: ${marketplaceName}\n${commandErrorText(e)}`);
|
|
674
|
+
failures.push(`codex marketplace ${marketplaceName}`);
|
|
675
|
+
}
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
620
678
|
try {
|
|
621
679
|
exec(addCommand, marketplaceExecOpts);
|
|
622
680
|
log.ok(`Codex marketplace ${marketplaceName} added`);
|
|
623
|
-
return;
|
|
624
681
|
}
|
|
625
682
|
catch (e) {
|
|
626
683
|
if (isCodexMarketplaceDifferentSource(e)) {
|
|
684
|
+
// Defense-in-depth: config.toml didn't claim the name but Codex CLI
|
|
685
|
+
// refused with "different source" — rare divergence between Codex
|
|
686
|
+
// internal state and config.toml.
|
|
627
687
|
const msg = `Codex marketplace ${marketplaceName} is already added from a different source`;
|
|
628
688
|
log.error(`${msg}\n${commandErrorText(e)}`);
|
|
629
689
|
failures.push(msg);
|
|
630
690
|
return;
|
|
631
691
|
}
|
|
632
|
-
|
|
633
|
-
try {
|
|
634
|
-
exec(codexMarketplaceUpgradeCommand(marketplaceName), marketplaceExecOpts);
|
|
635
|
-
log.ok(`Codex marketplace ${marketplaceName} upgraded`);
|
|
636
|
-
return;
|
|
637
|
-
}
|
|
638
|
-
catch (upgradeErr) {
|
|
639
|
-
// Surface the underlying upgrade error so a 6-month-out reader
|
|
640
|
-
// can tell apart ENOENT / network / auth / git failures.
|
|
641
|
-
log.error(`Failed to upgrade Codex marketplace: ${marketplaceName}\n${commandErrorText(upgradeErr)}`);
|
|
642
|
-
failures.push(`codex marketplace ${marketplaceName}`);
|
|
643
|
-
return;
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
// Same: surface the add error rather than masking ENOENT / network / auth.
|
|
692
|
+
// Surface the add error rather than masking ENOENT / network / auth.
|
|
647
693
|
log.error(`Failed to add Codex marketplace: ${marketplaceName}\n${commandErrorText(e)}`);
|
|
648
694
|
failures.push(`codex marketplace ${marketplaceName}`);
|
|
649
695
|
}
|
|
@@ -726,7 +772,7 @@ async function installCodexPlugins(packageRoot, opts) {
|
|
|
726
772
|
? { inherit: true }
|
|
727
773
|
: undefined;
|
|
728
774
|
if (localMarketplace) {
|
|
729
|
-
await addCodexMarketplaceWithRetry(localMarketplace.name, codexMarketplaceAddCommand(packageRoot), opts, marketplaceExecOpts, failures);
|
|
775
|
+
await addCodexMarketplaceWithRetry(localMarketplace.name, codexMarketplaceAddCommand(packageRoot), codexLocalMarketplaceSource(packageRoot), opts, marketplaceExecOpts, failures);
|
|
730
776
|
}
|
|
731
777
|
// Dedupe external marketplaces by name — multiple plugins from the same
|
|
732
778
|
// upstream share a single `marketplace add` call.
|
|
@@ -735,7 +781,7 @@ async function installCodexPlugins(packageRoot, opts) {
|
|
|
735
781
|
uniqueExternalMarketplaces.set(p.marketplace.name, p.marketplace);
|
|
736
782
|
}
|
|
737
783
|
for (const mp of uniqueExternalMarketplaces.values()) {
|
|
738
|
-
await addCodexMarketplaceWithRetry(mp.name, codexExternalMarketplaceAddCommand(mp.source), opts, marketplaceExecOpts, failures);
|
|
784
|
+
await addCodexMarketplaceWithRetry(mp.name, codexExternalMarketplaceAddCommand(mp.source), codexExternalMarketplaceSource(mp.source), opts, marketplaceExecOpts, failures);
|
|
739
785
|
}
|
|
740
786
|
if (failures.length === 0) {
|
|
741
787
|
const localMarketplaceContentRoot = localMarketplace
|
package/package.json
CHANGED