@@ -9,9 +9,18 @@ import type { OpenClawConfig } from "../../../config/types.openclaw.js";
99import type { PluginInstallRecord } from "../../../config/types.plugins.js" ;
1010import { parseClawHubPluginSpec } from "../../../infra/clawhub-spec.js" ;
1111import { parseRegistryNpmSpec } from "../../../infra/npm-registry-spec.js" ;
12+ import {
13+ normalizeUpdateChannel ,
14+ resolveRegistryUpdateChannel ,
15+ type UpdateChannel ,
16+ } from "../../../infra/update-channels.js" ;
1217import { resolveConfiguredChannelPresencePolicy } from "../../../plugins/channel-plugin-ids.js" ;
1318import { buildClawHubPluginInstallRecordFields } from "../../../plugins/clawhub-install-records.js" ;
1419import { CLAWHUB_INSTALL_ERROR_CODE , installPluginFromClawHub } from "../../../plugins/clawhub.js" ;
20+ import {
21+ resolveClawHubInstallSpecsForUpdateChannel ,
22+ resolveNpmInstallSpecsForUpdateChannel ,
23+ } from "../../../plugins/install-channel-specs.js" ;
1524import { resolveDefaultPluginExtensionsDir } from "../../../plugins/install-paths.js" ;
1625import { installPluginFromNpmSpec } from "../../../plugins/install.js" ;
1726import { loadInstalledPluginIndexInstallRecords } from "../../../plugins/installed-plugin-index-records.js" ;
@@ -32,6 +41,7 @@ import { updateNpmInstalledPlugins } from "../../../plugins/update.js";
3241import { resolveWebSearchInstallCatalogEntry } from "../../../plugins/web-search-install-catalog.js" ;
3342import { normalizeOptionalLowercaseString } from "../../../shared/string-coerce.js" ;
3443import { resolveUserPath } from "../../../utils.js" ;
44+ import { VERSION } from "../../../version.js" ;
3545import { asObjectRecord } from "./object.js" ;
3646
3747type DownloadableInstallCandidate = {
@@ -457,6 +467,7 @@ function recordClawHubPackageName(value: string | undefined): string | undefined
457467async function installCandidate ( params : {
458468 candidate : DownloadableInstallCandidate ;
459469 records : Record < string , PluginInstallRecord > ;
470+ updateChannel ?: UpdateChannel ;
460471} ) : Promise < {
461472 records : Record < string , PluginInstallRecord > ;
462473 changes : string [ ] ;
@@ -465,9 +476,23 @@ async function installCandidate(params: {
465476 const { candidate } = params ;
466477 const extensionsDir = resolveDefaultPluginExtensionsDir ( ) ;
467478 const changes : string [ ] = [ ] ;
468- if ( candidate . clawhubSpec && candidate . defaultChoice !== "npm" ) {
479+ const clawhubSpecs = candidate . clawhubSpec
480+ ? resolveClawHubInstallSpecsForUpdateChannel ( {
481+ spec : candidate . clawhubSpec ,
482+ updateChannel : params . updateChannel ,
483+ } )
484+ : null ;
485+ const npmSpecs = candidate . npmSpec
486+ ? resolveNpmInstallSpecsForUpdateChannel ( {
487+ spec : candidate . npmSpec ,
488+ updateChannel : params . updateChannel ,
489+ } )
490+ : null ;
491+ const clawhubInstallSpec = clawhubSpecs ?. installSpec ?? candidate . clawhubSpec ;
492+ const npmInstallSpec = npmSpecs ?. installSpec ?? candidate . npmSpec ;
493+ if ( clawhubInstallSpec && candidate . defaultChoice !== "npm" ) {
469494 const clawhubResult = await installPluginFromClawHub ( {
470- spec : candidate . clawhubSpec ,
495+ spec : clawhubInstallSpec ,
471496 extensionsDir,
472497 expectedPluginId : candidate . pluginId ,
473498 mode : "install" ,
@@ -479,31 +504,29 @@ async function installCandidate(params: {
479504 ...params . records ,
480505 [ pluginId ] : {
481506 ...buildClawHubPluginInstallRecordFields ( clawhubResult . clawhub ) ,
482- spec : candidate . clawhubSpec ,
507+ spec : clawhubSpecs ?. recordSpec ?? clawhubInstallSpec ,
483508 installPath : clawhubResult . targetDir ,
484509 installedAt : new Date ( ) . toISOString ( ) ,
485510 } ,
486511 } ,
487- changes : [
488- `Installed missing configured plugin "${ pluginId } " from ${ candidate . clawhubSpec } .` ,
489- ] ,
512+ changes : [ `Installed missing configured plugin "${ pluginId } " from ${ clawhubInstallSpec } .` ] ,
490513 warnings : [ ] ,
491514 } ;
492515 }
493- if ( ! candidate . npmSpec || ! shouldFallbackClawHubToNpm ( clawhubResult ) ) {
516+ if ( ! npmInstallSpec || ! shouldFallbackClawHubToNpm ( clawhubResult ) ) {
494517 return {
495518 records : params . records ,
496519 changes : [ ] ,
497520 warnings : [
498- `Failed to install missing configured plugin "${ candidate . pluginId } " from ${ candidate . clawhubSpec } : ${ clawhubResult . error } ` ,
521+ `Failed to install missing configured plugin "${ candidate . pluginId } " from ${ clawhubInstallSpec } : ${ clawhubResult . error } ` ,
499522 ] ,
500523 } ;
501524 }
502525 changes . push (
503- `ClawHub ${ candidate . clawhubSpec } unavailable for "${ candidate . pluginId } "; falling back to npm ${ candidate . npmSpec } .` ,
526+ `ClawHub ${ clawhubInstallSpec } unavailable for "${ candidate . pluginId } "; falling back to npm ${ npmInstallSpec } .` ,
504527 ) ;
505528 }
506- if ( ! candidate . npmSpec ) {
529+ if ( ! npmInstallSpec ) {
507530 return {
508531 records : params . records ,
509532 changes : [ ] ,
@@ -513,7 +536,7 @@ async function installCandidate(params: {
513536 } ;
514537 }
515538 const result = await installPluginFromNpmSpec ( {
516- spec : candidate . npmSpec ,
539+ spec : npmInstallSpec ,
517540 extensionsDir,
518541 expectedPluginId : candidate . pluginId ,
519542 expectedIntegrity : candidate . expectedIntegrity ,
@@ -527,7 +550,7 @@ async function installCandidate(params: {
527550 records : params . records ,
528551 changes : [ ] ,
529552 warnings : [
530- `Failed to install missing configured plugin "${ candidate . pluginId } " from ${ candidate . npmSpec } : ${ result . error } ` ,
553+ `Failed to install missing configured plugin "${ candidate . pluginId } " from ${ npmInstallSpec } : ${ result . error } ` ,
531554 ] ,
532555 } ;
533556 }
@@ -537,7 +560,7 @@ async function installCandidate(params: {
537560 ...params . records ,
538561 [ pluginId ] : {
539562 source : "npm" ,
540- spec : candidate . npmSpec ,
563+ spec : npmSpecs ?. recordSpec ?? npmInstallSpec ,
541564 installPath : result . targetDir ,
542565 version : result . version ,
543566 installedAt : new Date ( ) . toISOString ( ) ,
@@ -546,7 +569,7 @@ async function installCandidate(params: {
546569 } ,
547570 changes : [
548571 ...changes ,
549- `Installed missing configured plugin "${ pluginId } " from ${ candidate . npmSpec } .` ,
572+ `Installed missing configured plugin "${ pluginId } " from ${ npmInstallSpec } .` ,
550573 ] ,
551574 warnings : [ ] ,
552575 } ;
@@ -642,6 +665,10 @@ async function repairMissingPluginInstalls(params: {
642665 const changes : string [ ] = [ ] ;
643666 const warnings : string [ ] = [ ] ;
644667 const deferredPluginIds = new Set < string > ( ) ;
668+ const updateChannel = resolveRegistryUpdateChannel ( {
669+ configChannel : normalizeUpdateChannel ( params . cfg . update ?. channel ) ,
670+ currentVersion : VERSION ,
671+ } ) ;
645672 let nextRecords = records ;
646673
647674 for ( const [ pluginId , record ] of Object . entries ( records ) ) {
@@ -700,7 +727,7 @@ async function repairMissingPluginInstalls(params: {
700727 } ,
701728 } ,
702729 pluginIds : missingRecordedPluginIds ,
703- updateChannel : params . cfg . update ?. channel ,
730+ updateChannel,
704731 logger : {
705732 warn : ( message ) => warnings . push ( message ) ,
706733 error : ( message ) => warnings . push ( message ) ,
@@ -754,7 +781,7 @@ async function repairMissingPluginInstalls(params: {
754781 if ( hasUsableRecord ) {
755782 continue ;
756783 }
757- const installed = await installCandidate ( { candidate, records : nextRecords } ) ;
784+ const installed = await installCandidate ( { candidate, records : nextRecords , updateChannel } ) ;
758785 nextRecords = installed . records ;
759786 changes . push ( ...installed . changes ) ;
760787 warnings . push ( ...installed . warnings ) ;
0 commit comments