mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
refactor: remove dead plugin loader exports (#105937)
* refactor(plugins): trim activation and contract exports * test(plugins): restore fixture cleanup * refactor(plugins): trim install and loader exports * test(plugins): fully reset loader caches * refactor(plugins): trim metadata and catalog exports * test(plugins): preserve catalog trust coverage * refactor(plugins): trim provider and plugin exports * refactor(plugins): trim runtime and tool exports * test(plugins): update dead-export consumers * test(plugins): remove empty dead-export suites * refactor(plugins): align exports with split registry * refactor(plugins): trim drifted loader exports * style(plugins): format test fixtures * refactor(scripts): use supported plugin APIs * refactor(plugins): finish dead export cleanup * chore(deadcode): refresh export baseline * test(cli): mock production memory state * chore(deadcode): sync latest export baseline * fix(tests): keep plugin fixtures inside core * chore(deadcode): refresh rebased export baseline * chore(deadcode): sync current ratchets * fix(plugins): retain reserved slot invariant * fix(plugins): preserve dead-export invariants * test(plugins): use neutral catalog query fixture * test(plugins): satisfy catalog lint * test(plugins): preserve integrity drift coverage * fix(ci): register skill experience live proof
This commit is contained in:
@@ -3046,549 +3046,13 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
|
||||
"src/plugin-state/plugin-state-store.sqlite.ts: seedPluginStateDatabaseEntriesForTests",
|
||||
"src/plugin-state/plugin-state-store.sqlite.ts: setMaxPluginStateEntriesPerPluginForTests",
|
||||
"src/plugin-state/plugin-state-store.ts: clearPluginStateStoreForTests",
|
||||
"src/plugins/activation-context.ts: BundledPluginCompatibleActivationInputs",
|
||||
"src/plugins/activation-context.ts: BundledPluginCompatibleLoadValues",
|
||||
"src/plugins/activation-context.ts: PluginActivationCompatConfig",
|
||||
"src/plugins/activation-context.ts: PluginActivationInputs",
|
||||
"src/plugins/activation-planner.ts: PluginActivationPlanEntry",
|
||||
"src/plugins/activation-planner.ts: PluginActivationPlannerHintReason",
|
||||
"src/plugins/activation-planner.ts: PluginActivationPlannerManifestReason",
|
||||
"src/plugins/activation-planner.ts: PluginActivationPlannerReason",
|
||||
"src/plugins/activation-planner.ts: PluginActivationPlannerTrigger",
|
||||
"src/plugins/agent-tool-result-middleware-loader.ts: __testing",
|
||||
"src/plugins/agent-tool-result-middleware-loader.ts: testing",
|
||||
"src/plugins/agent-tool-result-middleware.ts: normalizeAgentToolResultMiddlewareHarnesses",
|
||||
"src/plugins/api-builder.ts: BuildPluginApiParams",
|
||||
"src/plugins/api-lifecycle.ts: PluginApiLifecyclePolicy",
|
||||
"src/plugins/api-lifecycle.ts: PluginApiMethodName",
|
||||
"src/plugins/bundle-commands.ts: ClaudeBundleCommandSpec",
|
||||
"src/plugins/bundle-config-shared.ts: BundleServerRuntimeSupport",
|
||||
"src/plugins/bundle-lsp.ts: BundleLspConfig",
|
||||
"src/plugins/bundle-lsp.ts: BundleLspRuntimeSupport",
|
||||
"src/plugins/bundle-manifest.ts: BundleManifestLoadResult",
|
||||
"src/plugins/bundle-manifest.ts: BundlePluginManifest",
|
||||
"src/plugins/bundle-mcp.ts: BundleMcpRuntimeSupport",
|
||||
"src/plugins/bundle-mcp.ts: EnabledBundleMcpConfigResult",
|
||||
"src/plugins/bundled-capability-runtime.ts: buildVitestCapabilityShimAliasMap",
|
||||
"src/plugins/bundled-channel-runtime.ts: resolveBundledChannelWorkspacePath",
|
||||
"src/plugins/bundled-dir.ts: setBundledPluginsDirOverrideForTest",
|
||||
"src/plugins/bundled-dir.ts: SourceCheckoutDependencyDiagnostic",
|
||||
"src/plugins/bundled-load-path-aliases.ts: BundledPluginLoadPathAlias",
|
||||
"src/plugins/bundled-load-path-aliases.ts: BundledPluginLoadPathAliasKind",
|
||||
"src/plugins/bundled-load-path-aliases.ts: LegacyBundledPluginPath",
|
||||
"src/plugins/bundled-load-path-aliases.ts: PackagedBundledPluginPath",
|
||||
"src/plugins/bundled-plugin-metadata.ts: BundledPluginMetadata",
|
||||
"src/plugins/bundled-plugin-startup-metadata.ts: BundledPluginStartupMetadata",
|
||||
"src/plugins/bundled-sources.ts: BundledPluginLookup",
|
||||
"src/plugins/clawhub.ts: ClawHubInstallErrorCode",
|
||||
"src/plugins/clawhub.ts: formatClawHubSpecifier",
|
||||
"src/plugins/cli-backend.types.ts: CliBackendToolAvailability",
|
||||
"src/plugins/cli-backends.runtime.ts: PluginCliBackendEntry",
|
||||
"src/plugins/cli-gateway-nodes-runtime.ts: resolvePluginCliNodeInvokeGatewayTimeoutMs",
|
||||
"src/plugins/command-registration.ts: CommandRegistrationResult",
|
||||
"src/plugins/command-registration.ts: RegisteredPluginCommand",
|
||||
"src/plugins/command-specs.ts: PluginCommandEntrySpec",
|
||||
"src/plugins/compaction-provider.ts: CompactionProviderSummarizationInstructions",
|
||||
"src/plugins/compaction-provider.ts: RegisteredCompactionProvider",
|
||||
"src/plugins/compat/registry.ts: isPluginCompatCode",
|
||||
"src/plugins/compat/registry.ts: KnownPluginCompatRecord",
|
||||
"src/plugins/compat/registry.ts: listDeprecatedPluginCompatRecords",
|
||||
"src/plugins/compat/registry.ts: PLUGIN_COMPAT_RECORDS",
|
||||
"src/plugins/compat/types.ts: PluginCompatOwner",
|
||||
"src/plugins/compat/types.ts: PluginCompatStatus",
|
||||
"src/plugins/config-activation-shared.ts: PluginActivationCause",
|
||||
"src/plugins/config-activation-shared.ts: PluginActivationDecision",
|
||||
"src/plugins/config-activation-shared.ts: PluginExplicitSelectionCause",
|
||||
"src/plugins/config-contract-matches.ts: PluginConfigContractMatch",
|
||||
"src/plugins/config-contracts.ts: PluginConfigContractMatch",
|
||||
"src/plugins/config-contracts.ts: PluginConfigContractMetadata",
|
||||
"src/plugins/config-policy.ts: isBundledChannelEnabledByChannelConfig",
|
||||
"src/plugins/config-policy.ts: NormalizedPluginsConfig",
|
||||
"src/plugins/config-policy.ts: PluginActivationSource",
|
||||
"src/plugins/config-policy.ts: PluginActivationState",
|
||||
"src/plugins/config-policy.ts: resolvePluginActivationState",
|
||||
"src/plugins/contracts/inventory/bundled-capability-metadata.ts: buildBundledPluginContractSnapshot",
|
||||
"src/plugins/contracts/inventory/bundled-capability-metadata.ts: BUNDLED_AUTO_ENABLE_PROVIDER_PLUGIN_IDS",
|
||||
"src/plugins/contracts/inventory/bundled-capability-metadata.ts: BUNDLED_LEGACY_PLUGIN_ID_ALIASES",
|
||||
"src/plugins/contracts/inventory/bundled-capability-metadata.ts: BundledCapabilityManifest",
|
||||
"src/plugins/contracts/inventory/bundled-capability-metadata.ts: hasBundledPluginContractSnapshotCapabilities",
|
||||
"src/plugins/contracts/inventory/bundled-capability-metadata.ts: resolveBundledContractSnapshotPluginIds",
|
||||
"src/plugins/contracts/registry.ts: providerContractPluginIds",
|
||||
"src/plugins/contracts/registry.ts: requireProviderContractProvider",
|
||||
"src/plugins/conversation-binding.ts: __testing",
|
||||
"src/plugins/conversation-binding.ts: testing",
|
||||
"src/plugins/current-plugin-metadata-snapshot.ts: resolvePluginMetadataControlPlaneFingerprint",
|
||||
"src/plugins/default-enablement.ts: PluginDefaultEnablement",
|
||||
"src/plugins/dependency-denylist.ts: blockedInstallDependencyPackageNames",
|
||||
"src/plugins/dependency-denylist.ts: BlockedManifestDependencyFinding",
|
||||
"src/plugins/doctor-contract-registry.ts: clearPluginDoctorContractRegistryCache",
|
||||
"src/plugins/doctor-contract-registry.ts: PluginDoctorStateMigrationEntry",
|
||||
"src/plugins/doctor-contract-registry.ts: setPluginDoctorContractRegistryModuleLoaderFactoryForTest",
|
||||
"src/plugins/embedding-provider-runtime.ts: EmbeddingInput",
|
||||
"src/plugins/embedding-provider-runtime.ts: EmbeddingProviderCallOptions",
|
||||
"src/plugins/embedding-provider-runtime.ts: EmbeddingProviderCreateOptions",
|
||||
"src/plugins/embedding-provider-runtime.ts: EmbeddingProviderCreateResult",
|
||||
"src/plugins/embedding-provider-runtime.ts: EmbeddingProviderRuntime",
|
||||
"src/plugins/embedding-provider-runtime.ts: listRegisteredEmbeddingProviders",
|
||||
"src/plugins/embedding-provider-runtime.ts: RegisteredEmbeddingProvider",
|
||||
"src/plugins/embedding-providers.ts: getEmbeddingProvider",
|
||||
"src/plugins/embedding-providers.ts: listEmbeddingProviders",
|
||||
"src/plugins/embedding-providers.ts: restoreEmbeddingProviders",
|
||||
"src/plugins/externalized-bundled-plugins.ts: ExternalizedBundledPluginPreferredSource",
|
||||
"src/plugins/gateway-startup-plugin-ids.ts: ConfiguredMemoryEmbeddingStartupProviderOwner",
|
||||
"src/plugins/gateway-startup-plugin-ids.ts: MemoryEmbeddingStartupProviderSource",
|
||||
"src/plugins/git-install.ts: GitPluginInstallResult",
|
||||
"src/plugins/git-install.ts: GitPluginResolution",
|
||||
"src/plugins/git-install.ts: ParsedGitPluginSpec",
|
||||
"src/plugins/hardlink-policy.ts: isNixStorePluginRoot",
|
||||
"src/plugins/hook-agent-context.ts: resolveAgentHookChannelId",
|
||||
"src/plugins/hook-decision-types.ts: BLOCK_MESSAGE_PREFIX",
|
||||
"src/plugins/hook-decision-types.ts: HookDecision",
|
||||
"src/plugins/hook-decision-types.ts: HookDecisionBlock",
|
||||
"src/plugins/hook-decision-types.ts: HookDecisionPass",
|
||||
"src/plugins/hook-decision-types.ts: mergeHookDecisions",
|
||||
"src/plugins/hook-registry.types.ts: PluginLegacyHookRegistration",
|
||||
"src/plugins/hook-runner-global-state.ts: HookRunnerGlobalState",
|
||||
"src/plugins/hooks.ts: HookFailurePolicy",
|
||||
"src/plugins/hooks.ts: HookRunnerLogger",
|
||||
"src/plugins/hooks.ts: HookRunnerOptions",
|
||||
"src/plugins/hooks.ts: PluginHookAfterCompactionEvent",
|
||||
"src/plugins/hooks.ts: PluginHookAfterToolCallEvent",
|
||||
"src/plugins/hooks.ts: PluginHookAgentContext",
|
||||
"src/plugins/hooks.ts: PluginHookAgentEndEvent",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeAgentFinalizeEvent",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeAgentFinalizeResult",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeAgentReplyEvent",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeAgentReplyResult",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeAgentRunEvent",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeAgentStartEvent",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeAgentStartResult",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeCompactionEvent",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeDispatchContext",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeDispatchEvent",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeDispatchResult",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeInstallContext",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeInstallEvent",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeInstallResult",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeMessageWriteEvent",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeMessageWriteResult",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeModelResolveEvent",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeModelResolveResult",
|
||||
"src/plugins/hooks.ts: PluginHookBeforePromptBuildEvent",
|
||||
"src/plugins/hooks.ts: PluginHookBeforePromptBuildResult",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeResetEvent",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeToolCallEvent",
|
||||
"src/plugins/hooks.ts: PluginHookBeforeToolCallResult",
|
||||
"src/plugins/hooks.ts: PluginHookCronChangedEvent",
|
||||
"src/plugins/hooks.ts: PluginHookCronReconciledContext",
|
||||
"src/plugins/hooks.ts: PluginHookCronReconciledEvent",
|
||||
"src/plugins/hooks.ts: PluginHookGatewayContext",
|
||||
"src/plugins/hooks.ts: PluginHookGatewayCronDeliveryStatus",
|
||||
"src/plugins/hooks.ts: PluginHookGatewayCronJobState",
|
||||
"src/plugins/hooks.ts: PluginHookGatewayCronRunStatus",
|
||||
"src/plugins/hooks.ts: PluginHookGatewayStartEvent",
|
||||
"src/plugins/hooks.ts: PluginHookGatewayStopEvent",
|
||||
"src/plugins/hooks.ts: PluginHookInboundClaimContext",
|
||||
"src/plugins/hooks.ts: PluginHookInboundClaimEvent",
|
||||
"src/plugins/hooks.ts: PluginHookInboundClaimResult",
|
||||
"src/plugins/hooks.ts: PluginHookLlmInputEvent",
|
||||
"src/plugins/hooks.ts: PluginHookLlmOutputEvent",
|
||||
"src/plugins/hooks.ts: PluginHookMessageContext",
|
||||
"src/plugins/hooks.ts: PluginHookMessageReceivedEvent",
|
||||
"src/plugins/hooks.ts: PluginHookMessageSendingEvent",
|
||||
"src/plugins/hooks.ts: PluginHookMessageSendingResult",
|
||||
"src/plugins/hooks.ts: PluginHookMessageSentEvent",
|
||||
"src/plugins/hooks.ts: PluginHookModelCallEndedEvent",
|
||||
"src/plugins/hooks.ts: PluginHookModelCallStartedEvent",
|
||||
"src/plugins/hooks.ts: PluginHookReplyDispatchContext",
|
||||
"src/plugins/hooks.ts: PluginHookReplyDispatchEvent",
|
||||
"src/plugins/hooks.ts: PluginHookReplyDispatchResult",
|
||||
"src/plugins/hooks.ts: PluginHookReplyPayload",
|
||||
"src/plugins/hooks.ts: PluginHookReplyPayloadSendingContext",
|
||||
"src/plugins/hooks.ts: PluginHookReplyPayloadSendingEvent",
|
||||
"src/plugins/hooks.ts: PluginHookReplyPayloadSendingResult",
|
||||
"src/plugins/hooks.ts: PluginHookResolveExecEnvContext",
|
||||
"src/plugins/hooks.ts: PluginHookResolveExecEnvEvent",
|
||||
"src/plugins/hooks.ts: PluginHookSessionContext",
|
||||
"src/plugins/hooks.ts: PluginHookSessionEndEvent",
|
||||
"src/plugins/hooks.ts: PluginHookSessionStartEvent",
|
||||
"src/plugins/hooks.ts: PluginHookSubagentContext",
|
||||
"src/plugins/hooks.ts: PluginHookSubagentDeliveryTargetEvent",
|
||||
"src/plugins/hooks.ts: PluginHookSubagentDeliveryTargetResult",
|
||||
"src/plugins/hooks.ts: PluginHookSubagentEndedEvent",
|
||||
"src/plugins/hooks.ts: PluginHookSubagentSpawnedEvent",
|
||||
"src/plugins/hooks.ts: PluginHookSubagentSpawningEvent",
|
||||
"src/plugins/hooks.ts: PluginHookSubagentSpawningResult",
|
||||
"src/plugins/hooks.ts: PluginHookToolContext",
|
||||
"src/plugins/hooks.ts: PluginHookToolResultPersistContext",
|
||||
"src/plugins/hooks.ts: PluginHookToolResultPersistEvent",
|
||||
"src/plugins/hooks.ts: PluginHookToolResultPersistResult",
|
||||
"src/plugins/hooks.ts: PluginTargetedInboundClaimOutcome",
|
||||
"src/plugins/host-hook-attachments.ts: attachmentProbeFs",
|
||||
"src/plugins/host-hook-attachments.ts: resolveAttachmentDelivery",
|
||||
"src/plugins/host-hook-attachments.ts: resolveSessionAttachmentThreadId",
|
||||
"src/plugins/host-hook-cleanup.ts: clearPluginOwnedSessionState",
|
||||
"src/plugins/host-hook-cleanup.ts: PluginHostCleanupFailure",
|
||||
"src/plugins/host-hook-cleanup.ts: PluginHostCleanupResult",
|
||||
"src/plugins/host-hook-json.ts: PluginJsonPrimitive",
|
||||
"src/plugins/host-hook-json.ts: PluginJsonValueLimits",
|
||||
"src/plugins/host-hook-runtime.ts: listPluginSessionSchedulerJobs",
|
||||
"src/plugins/host-hook-runtime.ts: PLUGIN_TERMINAL_EVENT_CLEANUP_WAIT_MS",
|
||||
"src/plugins/host-hook-scheduled-turns.ts: buildPluginSchedulerCronName",
|
||||
"src/plugins/host-hook-state.ts: clearPluginOwnedSessionState",
|
||||
"src/plugins/host-hook-state.ts: drainPluginNextTurnInjections",
|
||||
"src/plugins/host-hooks.ts: PluginControlUiTabGroup",
|
||||
"src/plugins/host-hooks.ts: PluginJsonPrimitive",
|
||||
"src/plugins/host-hooks.ts: PluginNextTurnInjectionPlacement",
|
||||
"src/plugins/host-hooks.ts: PluginSessionAttachmentFile",
|
||||
"src/plugins/host-hooks.ts: PluginSessionExtensionProjectionContext",
|
||||
"src/plugins/host-hooks.ts: PluginToolPolicyDecision",
|
||||
"src/plugins/host-tool-param-parsers.ts: HostToolDerivationOptions",
|
||||
"src/plugins/host-tool-param-parsers.ts: HostToolDerivedParams",
|
||||
"src/plugins/install-channel-specs.ts: ChannelInstallSpecs",
|
||||
"src/plugins/install-policy-context.ts: BeforeInstallHookPayloadParams",
|
||||
"src/plugins/install-security-scan.ts: PackageExecutableScanMetadata",
|
||||
"src/plugins/install-security-scan.ts: PluginInstallRequestKind",
|
||||
"src/plugins/install-source-info.ts: DescribePluginInstallSourceOptions",
|
||||
"src/plugins/install-source-info.ts: PluginInstallClawHubSourceInfo",
|
||||
"src/plugins/install-source-info.ts: PluginInstallLocalSourceInfo",
|
||||
"src/plugins/install-source-info.ts: PluginInstallNpmPinState",
|
||||
"src/plugins/install-source-info.ts: PluginInstallNpmSourceInfo",
|
||||
"src/plugins/install-source-info.ts: PluginInstallSourceWarning",
|
||||
"src/plugins/install.ts: installPluginFromDir",
|
||||
"src/plugins/install.ts: PluginInstallErrorCode",
|
||||
"src/plugins/install.ts: PluginNpmIntegrityDriftParams",
|
||||
"src/plugins/installed-plugin-index-record-cache.ts: InstallRecordsCacheEntry",
|
||||
"src/plugins/installed-plugin-index-store.ts: InstalledPluginIndexStoreState",
|
||||
"src/plugins/installed-plugin-index.ts: CONFIG_PATH_ACTIVATION_COMPAT_CODE",
|
||||
"src/plugins/installed-plugin-index.ts: InstalledPluginPackageChannelInfo",
|
||||
"src/plugins/installed-plugin-index.ts: InstalledPluginStartupInfo",
|
||||
"src/plugins/installed-plugin-index.ts: listEnabledInstalledPluginRecords",
|
||||
"src/plugins/interactive-registry.ts: clearPluginInteractiveHandlerRegistrations",
|
||||
"src/plugins/legacy-npm-declaration.ts: LegacyNpmPluginDeclaration",
|
||||
"src/plugins/loader-cache-state.ts: PluginLoadReentryError",
|
||||
"src/plugins/loader-channel-setup.ts: BundledRuntimeChannelRegistration",
|
||||
"src/plugins/loader-provenance.ts: PluginProvenanceIndex",
|
||||
"src/plugins/loader.ts: __testing",
|
||||
"src/plugins/loader.ts: clearPluginLoaderCache",
|
||||
"src/plugins/loader.ts: PluginLoadReentryError",
|
||||
"src/plugins/loader.ts: testing",
|
||||
"src/plugins/management-service.ts: derivePluginCategory",
|
||||
"src/plugins/management-service.ts: ManagedPluginCatalog",
|
||||
"src/plugins/management-service.ts: ManagedPluginCatalogEntry",
|
||||
"src/plugins/management-service.ts: ManagedPluginInstallRequest",
|
||||
"src/plugins/management-service.ts: overlayBundledOfficialPluginCatalogMetadata",
|
||||
"src/plugins/manifest-command-aliases.ts: PluginManifestCommandAliasKind",
|
||||
"src/plugins/manifest-contract-runtime.ts: ManifestContractRuntimePluginResolution",
|
||||
"src/plugins/manifest-contribution-ids.ts: listManifestContributionIds",
|
||||
"src/plugins/manifest-contribution-ids.ts: ListManifestContributionIdsParams",
|
||||
"src/plugins/manifest-registry.ts: __testing",
|
||||
"src/plugins/manifest-registry.ts: testing",
|
||||
"src/plugins/manifest-tool-availability.ts: ManifestAuthAvailabilitySignal",
|
||||
"src/plugins/manifest-tool-availability.ts: ManifestConfigAvailabilitySignal",
|
||||
"src/plugins/manifest.ts: clearPluginManifestLoadCache",
|
||||
"src/plugins/manifest.ts: ManifestKey",
|
||||
"src/plugins/manifest.ts: MAX_PLUGIN_MANIFEST_BYTES",
|
||||
"src/plugins/manifest.ts: OpenClawPackageCompat",
|
||||
"src/plugins/manifest.ts: OpenClawPackageSetupFeatures",
|
||||
"src/plugins/manifest.ts: OpenClawPackageStartup",
|
||||
"src/plugins/manifest.ts: PluginManifestCapabilityProviderModeConfigSignal",
|
||||
"src/plugins/manifest.ts: PluginManifestConfigLiteral",
|
||||
"src/plugins/manifest.ts: PluginManifestDangerousConfigFlag",
|
||||
"src/plugins/manifest.ts: PluginManifestDefaultPlatform",
|
||||
"src/plugins/manifest.ts: PluginManifestLoadResult",
|
||||
"src/plugins/manifest.ts: PluginManifestMediaUnderstandingCapability",
|
||||
"src/plugins/manifest.ts: PluginManifestModelIdPrefixRule",
|
||||
"src/plugins/manifest.ts: PluginManifestOnboardingScope",
|
||||
"src/plugins/manifest.ts: PluginManifestProviderAuthChoice",
|
||||
"src/plugins/manifest.ts: PluginManifestProviderBaseUrlGuard",
|
||||
"src/plugins/manifest.ts: PluginManifestProviderRequestProvider",
|
||||
"src/plugins/manifest.ts: PluginManifestSecretInputContracts",
|
||||
"src/plugins/manifest.ts: PluginManifestSecretInputPath",
|
||||
"src/plugins/manifest.ts: PluginManifestSetupProvider",
|
||||
"src/plugins/manifest.ts: PluginManifestSetupProviderAuthEvidence",
|
||||
"src/plugins/manifest.ts: PluginPackageChannelCliOption",
|
||||
"src/plugins/marketplace.ts: MarketplaceInstallResult",
|
||||
"src/plugins/marketplace.ts: MarketplaceManifest",
|
||||
"src/plugins/marketplace.ts: MarketplacePluginEntry",
|
||||
"src/plugins/marketplace.ts: MarketplacePluginListResult",
|
||||
"src/plugins/marketplace.ts: MarketplaceShortcutResolution",
|
||||
"src/plugins/memory-embedding-providers.ts: restoreMemoryEmbeddingProviders",
|
||||
"src/plugins/memory-state.ts: MemoryPluginCapabilityRegistration",
|
||||
"src/plugins/memory-state.ts: MemoryPluginPublicArtifactContentType",
|
||||
"src/plugins/memory-state.ts: MemoryPromptSupplementRegistration",
|
||||
"src/plugins/memory-state.ts: MemoryRuntimeBackendConfig",
|
||||
"src/plugins/memory-state.ts: MemoryRuntimeQmdConfig",
|
||||
"src/plugins/memory-state.ts: registerMemoryFlushPlanResolver",
|
||||
"src/plugins/memory-state.ts: registerMemoryPromptSection",
|
||||
"src/plugins/memory-state.ts: registerMemoryRuntime",
|
||||
"src/plugins/min-host-version.ts: MIN_HOST_VERSION_FORMAT",
|
||||
"src/plugins/min-host-version.ts: MinHostVersionCheckResult",
|
||||
"src/plugins/min-host-version.ts: MinHostVersionRequirement",
|
||||
"src/plugins/official-external-plugin-catalog-envelope.ts: createOfficialExternalPluginCatalogEnvelopePayload",
|
||||
"src/plugins/official-external-plugin-catalog-envelope.ts: createOfficialExternalPluginCatalogEnvelopeSigningInput",
|
||||
"src/plugins/official-external-plugin-catalog-envelope.ts: OFFICIAL_EXTERNAL_PLUGIN_CATALOG_FEED_PAYLOAD_TYPE",
|
||||
"src/plugins/official-external-plugin-catalog-envelope.ts: OfficialExternalPluginCatalogEnvelopeSignature",
|
||||
"src/plugins/official-external-plugin-catalog-envelope.ts: OfficialExternalPluginCatalogEnvelopeVerificationResult",
|
||||
"src/plugins/official-external-plugin-catalog-envelope.ts: OfficialExternalPluginCatalogSignedEnvelope",
|
||||
"src/plugins/official-external-plugin-catalog-envelope.ts: OfficialExternalPluginCatalogTrustedSigningKey",
|
||||
"src/plugins/official-external-plugin-catalog-snapshot-store.ts: HostedOfficialExternalPluginCatalogSnapshotStoreOptions",
|
||||
"src/plugins/official-external-plugin-catalog.ts: createInMemoryHostedOfficialExternalPluginCatalogSnapshotStore",
|
||||
"src/plugins/official-external-plugin-catalog.ts: DEFAULT_OFFICIAL_EXTERNAL_PLUGIN_CATALOG_CLAWHUB_SOURCE_REF",
|
||||
"src/plugins/official-external-plugin-catalog.ts: DEFAULT_OFFICIAL_EXTERNAL_PLUGIN_CATALOG_FEED_PROFILE",
|
||||
"src/plugins/official-external-plugin-catalog.ts: DEFAULT_OFFICIAL_EXTERNAL_PLUGIN_CATALOG_FEED_URL",
|
||||
"src/plugins/official-external-plugin-catalog.ts: DEFAULT_OFFICIAL_EXTERNAL_PLUGIN_CATALOG_NPM_SOURCE_REF",
|
||||
"src/plugins/official-external-plugin-catalog.ts: filterOfficialExternalPluginCatalogEntriesBySourceRefs",
|
||||
"src/plugins/official-external-plugin-catalog.ts: loadHostedOfficialExternalPluginCatalogEntries",
|
||||
"src/plugins/official-external-plugin-catalog.ts: OfficialExternalPluginCatalogFeedProfile",
|
||||
"src/plugins/official-external-plugin-catalog.ts: OfficialExternalPluginCatalogFeedSigningKey",
|
||||
"src/plugins/official-external-plugin-catalog.ts: OfficialExternalPluginCatalogFeedVerification",
|
||||
"src/plugins/official-external-plugin-catalog.ts: OfficialExternalPluginCatalogInstallCandidate",
|
||||
"src/plugins/official-external-plugin-catalog.ts: OfficialExternalPluginCatalogManifest",
|
||||
"src/plugins/official-external-plugin-catalog.ts: OfficialExternalPluginCatalogProfileConfig",
|
||||
"src/plugins/official-external-plugin-catalog.ts: OfficialExternalPluginCatalogSourceProfile",
|
||||
"src/plugins/official-external-plugin-catalog.ts: OfficialExternalProviderCatalogProvider",
|
||||
"src/plugins/official-external-plugin-catalog.ts: parseOfficialExternalPluginCatalogEntries",
|
||||
"src/plugins/official-external-plugin-catalog.ts: resolveOfficialExternalPluginCatalogProfileConfigFromConfig",
|
||||
"src/plugins/official-external-plugin-catalog.ts: validateOfficialExternalPluginCatalogEntrySourceRefs",
|
||||
"src/plugins/openai-compatible-embedding-provider.ts: createOpenAICompatibleEmbeddingProvider",
|
||||
"src/plugins/openai-compatible-embedding-provider.ts: OPENAI_COMPATIBLE_EMBEDDING_PROVIDER_ID",
|
||||
"src/plugins/openai-compatible-embedding-provider.ts: OpenAICompatibleEmbeddingClient",
|
||||
"src/plugins/package-compat.ts: PackagePluginApiRangeResult",
|
||||
"src/plugins/plugin-cache-primitives.ts: ConfigScopedPromiseLoader",
|
||||
"src/plugins/plugin-control-plane-context.ts: PluginControlPlaneContext",
|
||||
"src/plugins/plugin-control-plane-context.ts: PluginDiscoveryContext",
|
||||
"src/plugins/plugin-control-plane-context.ts: resolvePluginControlPlaneContext",
|
||||
"src/plugins/plugin-control-plane-context.ts: ResolvePluginDiscoveryContextParams",
|
||||
"src/plugins/plugin-control-plane-context.ts: resolvePluginDiscoveryFingerprint",
|
||||
"src/plugins/plugin-load-profile.ts: PluginLoadProfileExtras",
|
||||
"src/plugins/plugin-load-profile.ts: PluginLoadProfiler",
|
||||
"src/plugins/plugin-load-profile.ts: PluginLoadProfileScope",
|
||||
"src/plugins/plugin-lookup-table.ts: clearPluginLookUpTableMemoForTest",
|
||||
"src/plugins/plugin-lookup-table.ts: LoadPluginLookUpTableParams",
|
||||
"src/plugins/plugin-lookup-table.ts: PluginLookUpTableMetrics",
|
||||
"src/plugins/plugin-module-loader-cache.ts: PluginModuleLoader",
|
||||
"src/plugins/plugin-module-loader-cache.ts: PluginModuleLoaderCacheEntry",
|
||||
"src/plugins/plugin-module-loader-cache.ts: PluginModuleLoaderStatsSnapshot",
|
||||
"src/plugins/plugin-module-loader-cache.ts: resolvePluginModuleLoaderCacheEntry",
|
||||
"src/plugins/plugin-module-loader-cache.ts: ResolvePluginModuleLoaderCacheEntryParams",
|
||||
"src/plugins/plugin-registration-transaction.ts: PluginRegistrationTransaction",
|
||||
"src/plugins/plugin-registry-contributions.ts: ListPluginContributionIdsParams",
|
||||
"src/plugins/plugin-registry-contributions.ts: LoadPluginRegistryManifestParams",
|
||||
"src/plugins/plugin-registry-contributions.ts: PluginLookUpTable",
|
||||
"src/plugins/plugin-registry-contributions.ts: PluginRegistryContributionOptions",
|
||||
"src/plugins/plugin-registry-contributions.ts: PluginRegistryIdNormalizerOptions",
|
||||
"src/plugins/plugin-registry-contributions.ts: ResolveManifestContractOwnerPluginIdParams",
|
||||
"src/plugins/plugin-registry-contributions.ts: ResolveManifestContractPluginIdsByCompatibilityRuntimePathParams",
|
||||
"src/plugins/plugin-registry-contributions.ts: ResolveManifestContractPluginIdsParams",
|
||||
"src/plugins/plugin-registry-contributions.ts: ResolvePluginContributionOwnersParams",
|
||||
"src/plugins/plugin-registry-contributions.ts: ResolveProviderOwnersParams",
|
||||
"src/plugins/plugin-registry-snapshot.ts: DISABLE_PERSISTED_PLUGIN_REGISTRY_ENV",
|
||||
"src/plugins/plugin-registry-snapshot.ts: GetPluginRecordParams",
|
||||
"src/plugins/plugin-registry-snapshot.ts: listPluginRecords",
|
||||
"src/plugins/plugin-registry-snapshot.ts: PluginRegistryInspection",
|
||||
"src/plugins/plugin-registry-snapshot.ts: PluginRegistrySnapshotDiagnosticCode",
|
||||
"src/plugins/plugin-registry-snapshot.ts: PluginRegistrySnapshotResult",
|
||||
"src/plugins/plugin-sdk-native-resolver.ts: InstallOpenClawPluginSdkNativeResolverOptions",
|
||||
"src/plugins/plugin-sdk-native-resolver.ts: resetOpenClawPluginSdkNativeResolverForTest",
|
||||
"src/plugins/plugin-version-drift.ts: PluginVersionDriftEntry",
|
||||
"src/plugins/provider-auth-choice.ts: __testing",
|
||||
"src/plugins/provider-auth-choice.ts: applyAuthChoicePluginProvider",
|
||||
"src/plugins/provider-auth-choice.ts: ApplyProviderAuthChoiceParams",
|
||||
"src/plugins/provider-auth-choice.ts: ApplyProviderAuthChoiceResult",
|
||||
"src/plugins/provider-auth-choice.ts: PluginProviderAuthChoiceOptions",
|
||||
"src/plugins/provider-auth-choice.ts: testing",
|
||||
"src/plugins/provider-auth-choices.ts: ProviderOnboardAuthFlag (providerAuthChoices)",
|
||||
"src/plugins/provider-auth-choices.ts: resolveManifestProviderOnboardAuthFlags (providerAuthChoices)",
|
||||
"src/plugins/provider-auth-input.ts: extractEnvVarFromSourceLabel",
|
||||
"src/plugins/provider-auth-input.ts: maybeApplyApiKeyFromOption",
|
||||
"src/plugins/provider-auth-input.ts: resolveRefFallbackInput",
|
||||
"src/plugins/provider-auth-input.ts: SecretInputModePromptCopy",
|
||||
"src/plugins/provider-auth-input.ts: SecretRefSetupPromptCopy",
|
||||
"src/plugins/provider-auth-mode.ts: SecretInputModePromptCopy",
|
||||
"src/plugins/provider-auth-token.ts: ANTHROPIC_SETUP_TOKEN_PREFIX",
|
||||
"src/plugins/provider-catalog-result.ts: ProviderCatalogResultProjection",
|
||||
"src/plugins/provider-discovery.ts: resolveInstalledPluginProviderContributionIds",
|
||||
"src/plugins/provider-discovery.ts: ResolveInstalledPluginProviderContributionIdsParams",
|
||||
"src/plugins/provider-discovery.ts: ResolveRuntimePluginDiscoveryProvidersParams",
|
||||
"src/plugins/provider-hook-runtime.ts: ProviderRuntimePluginHandleParams",
|
||||
"src/plugins/provider-hook-runtime.ts: ProviderRuntimePluginLookupParams",
|
||||
"src/plugins/provider-model-compat.ts: shouldOmitEmptyArrayItems",
|
||||
"src/plugins/provider-oauth-flow.ts: OAuthPrompt",
|
||||
"src/plugins/provider-openai-chatgpt-oauth-tls.ts: OpenAIOAuthTlsPreflightResult",
|
||||
"src/plugins/provider-runtime.runtime.ts: buildProviderMissingAuthMessageWithPlugin",
|
||||
"src/plugins/provider-thinking.types.ts: ProviderThinkingLevel",
|
||||
"src/plugins/provider-thinking.types.ts: ProviderThinkingLevelId",
|
||||
"src/plugins/provider-thinking.types.ts: ProviderThinkingModelCompat",
|
||||
"src/plugins/provider-wizard.ts: ProviderWizardOption (providerWizard)",
|
||||
"src/plugins/providers.ts: __testing",
|
||||
"src/plugins/providers.ts: ProviderRefOwnership",
|
||||
"src/plugins/providers.ts: testing",
|
||||
"src/plugins/providers.ts: UsageHookProviderPluginContract",
|
||||
"src/plugins/public-surface-loader.ts: resetBundledPluginPublicArtifactLoaderForTest",
|
||||
"src/plugins/public-surface-runtime.ts: normalizeBundledPluginDirName",
|
||||
"src/plugins/register-plugin-cli-command-groups.ts: PluginCliCommandGroupEntry",
|
||||
"src/plugins/register-plugin-cli-command-groups.ts: PluginCliCommandGroupMode",
|
||||
"src/plugins/registry-types.ts: OpenClawPluginApi",
|
||||
"src/plugins/registry-types.ts: OpenClawPluginHookOptions",
|
||||
"src/plugins/registry-types.ts: OpenClawPluginHttpRouteParams",
|
||||
"src/plugins/registry-types.ts: OpenClawPluginNodeHostCommand",
|
||||
"src/plugins/registry-types.ts: OpenClawPluginToolContext",
|
||||
"src/plugins/registry-types.ts: PluginAgentEventSubscriptionRegistryRegistration",
|
||||
"src/plugins/registry-types.ts: PluginAgentHarnessRegistration",
|
||||
"src/plugins/registry-types.ts: PluginChannelSetupRegistration",
|
||||
"src/plugins/registry-types.ts: PluginCliBackendRegistration",
|
||||
"src/plugins/registry-types.ts: PluginCliRegistration",
|
||||
"src/plugins/registry-types.ts: PluginCodexAppServerExtensionFactoryRegistration",
|
||||
"src/plugins/registry-types.ts: PluginControlUiDescriptorRegistryRegistration",
|
||||
"src/plugins/registry-types.ts: PluginConversationBindingResolvedHandlerRegistration",
|
||||
"src/plugins/registry-types.ts: PluginEmbeddingProviderRegistration",
|
||||
"src/plugins/registry-types.ts: PluginHookHandlerMap",
|
||||
"src/plugins/registry-types.ts: PluginHookRegistration",
|
||||
"src/plugins/registry-types.ts: PluginHostedMediaResolverRegistration",
|
||||
"src/plugins/registry-types.ts: PluginImageGenerationProviderRegistration",
|
||||
"src/plugins/registry-types.ts: PluginInteractiveHandlerRegistryRegistration",
|
||||
"src/plugins/registry-types.ts: PluginMediaUnderstandingProviderRegistration",
|
||||
"src/plugins/registry-types.ts: PluginMemoryEmbeddingProviderRegistration",
|
||||
"src/plugins/registry-types.ts: PluginMigrationProviderRegistration",
|
||||
"src/plugins/registry-types.ts: PluginModelCatalogProviderRegistration",
|
||||
"src/plugins/registry-types.ts: PluginMusicGenerationProviderRegistration",
|
||||
"src/plugins/registry-types.ts: PluginNodeInvokePolicyRegistration",
|
||||
"src/plugins/registry-types.ts: PluginProviderRegistration",
|
||||
"src/plugins/registry-types.ts: PluginRealtimeTranscriptionProviderRegistration",
|
||||
"src/plugins/registry-types.ts: PluginRealtimeVoiceProviderRegistration",
|
||||
"src/plugins/registry-types.ts: PluginRegistrationMode",
|
||||
"src/plugins/registry-types.ts: PluginReloadRegistration",
|
||||
"src/plugins/registry-types.ts: PluginRuntimeLifecycleRegistryRegistration",
|
||||
"src/plugins/registry-types.ts: PluginSecurityAuditCollectorRegistration",
|
||||
"src/plugins/registry-types.ts: PluginSessionCatalogRegistration",
|
||||
"src/plugins/registry-types.ts: PluginSessionExtensionRegistryRegistration",
|
||||
"src/plugins/registry-types.ts: PluginSessionSchedulerJobRegistryRegistration",
|
||||
"src/plugins/registry-types.ts: PluginSpeechProviderRegistration",
|
||||
"src/plugins/registry-types.ts: PluginToolMetadataRegistryRegistration",
|
||||
"src/plugins/registry-types.ts: PluginTranscriptsSourceProviderRegistration",
|
||||
"src/plugins/registry-types.ts: PluginVideoGenerationProviderRegistration",
|
||||
"src/plugins/registry-types.ts: PluginWebFetchProviderRegistration",
|
||||
"src/plugins/registry-types.ts: PluginWebSearchProviderRegistration",
|
||||
"src/plugins/registry.ts: PluginAgentHarnessRegistration",
|
||||
"src/plugins/registry.ts: PluginChannelRegistration",
|
||||
"src/plugins/registry.ts: PluginChannelSetupRegistration",
|
||||
"src/plugins/registry.ts: PluginCliBackendRegistration",
|
||||
"src/plugins/registry.ts: PluginCliRegistration",
|
||||
"src/plugins/registry.ts: PluginCommandRegistration",
|
||||
"src/plugins/registry.ts: PluginControlUiDescriptorRegistryRegistration",
|
||||
"src/plugins/registry.ts: PluginConversationBindingResolvedHandlerRegistration",
|
||||
"src/plugins/registry.ts: PluginHookRegistration",
|
||||
"src/plugins/registry.ts: PluginHostedMediaResolverRegistration",
|
||||
"src/plugins/registry.ts: PluginImageGenerationProviderRegistration",
|
||||
"src/plugins/registry.ts: PluginMediaUnderstandingProviderRegistration",
|
||||
"src/plugins/registry.ts: PluginMemoryEmbeddingProviderRegistration",
|
||||
"src/plugins/registry.ts: PluginMusicGenerationProviderRegistration",
|
||||
"src/plugins/registry.ts: PluginNodeHostCommandRegistration",
|
||||
"src/plugins/registry.ts: PluginProviderRegistration",
|
||||
"src/plugins/registry.ts: PluginRealtimeTranscriptionProviderRegistration",
|
||||
"src/plugins/registry.ts: PluginRealtimeVoiceProviderRegistration",
|
||||
"src/plugins/registry.ts: PluginRegistryParams",
|
||||
"src/plugins/registry.ts: PluginReloadRegistration",
|
||||
"src/plugins/registry.ts: PluginRuntimeLifecycleRegistryRegistration",
|
||||
"src/plugins/registry.ts: PluginSecurityAuditCollectorRegistration",
|
||||
"src/plugins/registry.ts: PluginServiceRegistration",
|
||||
"src/plugins/registry.ts: PluginSessionExtensionRegistryRegistration",
|
||||
"src/plugins/registry.ts: PluginSpeechProviderRegistration",
|
||||
"src/plugins/registry.ts: PluginTextTransformsRegistration",
|
||||
"src/plugins/registry.ts: PluginToolMetadataRegistryRegistration",
|
||||
"src/plugins/registry.ts: PluginToolRegistration",
|
||||
"src/plugins/registry.ts: PluginTrustedToolPolicyRegistryRegistration",
|
||||
"src/plugins/registry.ts: PluginVideoGenerationProviderRegistration",
|
||||
"src/plugins/registry.ts: PluginWebFetchProviderRegistration",
|
||||
"src/plugins/registry.ts: PluginWebSearchProviderRegistration",
|
||||
"src/plugins/registry.ts: PluginWorkerProviderRegistration",
|
||||
"src/plugins/roots.ts: PluginCacheInputs",
|
||||
"src/plugins/runtime-channel-state.ts: PLUGIN_REGISTRY_STATE",
|
||||
"src/plugins/runtime-state.ts: getActivePluginChannelRegistryFromState",
|
||||
"src/plugins/runtime-state.ts: RuntimeTrackedPluginRegistry",
|
||||
"src/plugins/runtime/gateway-bindings.ts: clearGatewaySubagentRuntime",
|
||||
"src/plugins/runtime/gateway-request-scope.ts: PluginRuntimeGatewayRequestScope",
|
||||
"src/plugins/runtime/gateway-request-scope.ts: PluginRuntimePluginScope",
|
||||
"src/plugins/runtime/index.ts: clearGatewaySubagentRuntime",
|
||||
"src/plugins/runtime/index.ts: createPluginRuntime",
|
||||
"src/plugins/runtime/index.ts: CreatePluginRuntimeOptions",
|
||||
"src/plugins/runtime/index.ts: setGatewayNodesRuntime",
|
||||
"src/plugins/runtime/index.ts: setGatewaySubagentRuntime",
|
||||
"src/plugins/runtime/load-context.ts: PluginRuntimeLoadContextOptions",
|
||||
"src/plugins/runtime/load-context.ts: PluginRuntimeResolvedLoadValues",
|
||||
"src/plugins/runtime/native-deps.ts: NativeDependencyHintParams",
|
||||
"src/plugins/runtime/runtime-plugin-boundary.ts: resolvePluginRuntimeRecord",
|
||||
"src/plugins/runtime/runtime-taskflow.types.ts: BoundTaskFlowCancelResult",
|
||||
"src/plugins/runtime/runtime-taskflow.types.ts: BoundTaskFlowTaskRunResult",
|
||||
"src/plugins/runtime/runtime-taskflow.types.ts: ManagedTaskFlowCreateParams",
|
||||
"src/plugins/runtime/runtime-taskflow.types.ts: ManagedTaskFlowMutationErrorCode",
|
||||
"src/plugins/runtime/runtime-tasks.types.ts: TaskFlowView",
|
||||
"src/plugins/runtime/runtime-tasks.types.ts: TaskRunAggregateSummary",
|
||||
"src/plugins/runtime/runtime-tasks.types.ts: TaskRunDetail",
|
||||
"src/plugins/runtime/runtime-tasks.types.ts: TaskRunView",
|
||||
"src/plugins/runtime/types-channel.ts: PluginRuntimeChannelContextEvent",
|
||||
"src/plugins/runtime/types-channel.ts: PluginRuntimeChannelContextKey",
|
||||
"src/plugins/runtime/types-channel.ts: PluginRuntimeChannelContextRegistry",
|
||||
"src/plugins/runtime/types-channel.ts: RuntimeThreadBindingLifecycleRecord",
|
||||
"src/plugins/runtime/types-core.ts: DeepReadonly",
|
||||
"src/plugins/runtime/types-core.ts: HeartbeatRunResult",
|
||||
"src/plugins/runtime/types-core.ts: PluginRuntimeThinkingPolicy",
|
||||
"src/plugins/runtime/types-core.ts: PluginRuntimeThinkingPolicyLevel",
|
||||
"src/plugins/runtime/types-core.ts: PluginRuntimeThinkingPolicyRequest",
|
||||
"src/plugins/runtime/types-core.ts: RuntimeRequestHeartbeatNowOptions",
|
||||
"src/plugins/runtime/types-core.ts: RuntimeRequestHeartbeatOptions",
|
||||
"src/plugins/runtime/types.ts: PluginManagedWorktree",
|
||||
"src/plugins/runtime/types.ts: RuntimeNodeInvokeParams",
|
||||
"src/plugins/runtime/types.ts: RuntimeNodeListParams",
|
||||
"src/plugins/runtime/types.ts: RuntimeNodeListResult",
|
||||
"src/plugins/runtime/types.ts: SubagentDeleteSessionParams",
|
||||
"src/plugins/runtime/types.ts: SubagentGetSessionMessagesParams",
|
||||
"src/plugins/runtime/types.ts: SubagentGetSessionMessagesResult",
|
||||
"src/plugins/runtime/types.ts: SubagentGetSessionParams",
|
||||
"src/plugins/runtime/types.ts: SubagentGetSessionResult",
|
||||
"src/plugins/runtime/types.ts: SubagentWaitParams",
|
||||
"src/plugins/runtime/types.ts: SubagentWaitResult",
|
||||
"src/plugins/sdk-alias.ts: isBundledPluginExtensionPath",
|
||||
"src/plugins/sdk-alias.ts: LoaderModuleResolveParams",
|
||||
"src/plugins/sdk-alias.ts: normalizeJitiAliasTargetPath",
|
||||
"src/plugins/sdk-alias.ts: resolvePluginLoaderJitiFsCacheDir",
|
||||
"src/plugins/sdk-alias.ts: resolvePluginLoaderJitiFsCacheOption",
|
||||
"src/plugins/session-entry-slot-keys.ts: _AssertAllSessionEntryKeysAreReserved",
|
||||
"src/plugins/setup-registry.runtime.ts: testing",
|
||||
"src/plugins/setup-registry.ts: clearPluginSetupRegistryCache",
|
||||
"src/plugins/setup-registry.ts: PluginSetupRegistryDiagnosticCode",
|
||||
"src/plugins/setup-registry.ts: setPluginSetupRegistryModuleLoaderFactoryForTest",
|
||||
"src/plugins/slots.ts: normalizeKinds",
|
||||
"src/plugins/slots.ts: slotKeysForPluginKind",
|
||||
"src/plugins/slots.ts: SlotSelectionResult",
|
||||
"src/plugins/source-display.ts: formatPluginSourceForTable",
|
||||
"src/plugins/source-display.ts: PluginSourceRoots",
|
||||
"src/plugins/source-display.ts: resolvePluginSourceRoots",
|
||||
"src/plugins/status-dependencies-core.ts: PluginDependencyEntry",
|
||||
"src/plugins/tools.ts: PluginToolMeta",
|
||||
"src/plugins/tools.ts: resetPluginToolDescriptorCache",
|
||||
"src/plugins/tools.ts: resetPluginToolFactoryCache",
|
||||
"src/plugins/trusted-tool-policy.ts: TrustedToolPolicyDiagnosticEntry",
|
||||
"src/plugins/uninstall.ts: createEmptyUninstallActions",
|
||||
"src/plugins/uninstall.ts: PluginUninstallPlanResult",
|
||||
"src/plugins/uninstall.ts: resolveUninstallDirectoryTarget",
|
||||
"src/plugins/uninstall.ts: UninstallActions",
|
||||
"src/plugins/uninstall.ts: uninstallPlugin",
|
||||
"src/plugins/uninstall.ts: UninstallPluginParams",
|
||||
"src/plugins/uninstall.ts: UninstallPluginResult",
|
||||
"src/plugins/update.ts: PluginChannelSyncResult",
|
||||
"src/plugins/update.ts: PluginChannelSyncSummary",
|
||||
"src/plugins/update.ts: PluginUpdateLogger",
|
||||
"src/plugins/update.ts: PluginUpdateStatus",
|
||||
"src/plugins/update.ts: PluginUpdateSummary",
|
||||
"src/plugins/web-provider-resolution-shared.ts: WebProviderCandidateResolution",
|
||||
"src/plugins/web-provider-resolution-shared.ts: WebProviderConfigKey",
|
||||
"src/plugins/web-provider-resolution-shared.ts: WebProviderContract",
|
||||
"src/plugins/web-provider-runtime-shared.ts: ResolvePluginWebProvidersParams",
|
||||
"src/plugins/web-provider-types.ts: WebFetchProviderConfiguredCredentialFallback",
|
||||
"src/plugins/web-provider-types.ts: WebSearchProviderConfiguredCredentialFallback",
|
||||
"src/plugins/worker-provider-registry.ts: listWorkerProviderRegistrations",
|
||||
"src/process/command-queue.ts: CommandLaneTaskTimeoutError",
|
||||
"src/process/command-queue.ts: resetCommandQueueStateForTest",
|
||||
"src/process/gateway-work-admission.ts: tryBeginGatewayIndependentRootWorkAdmission",
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
// Bundled Extension Manifest script supports OpenClaw repository automation.
|
||||
import {
|
||||
MIN_HOST_VERSION_FORMAT,
|
||||
parseMinHostVersionRequirement,
|
||||
} from "../../src/plugins/min-host-version.ts";
|
||||
import { checkMinHostVersion } from "../../src/plugins/min-host-version.ts";
|
||||
import { isRecord } from "../../src/utils.js";
|
||||
|
||||
export type ExtensionPackageJson = {
|
||||
@@ -38,11 +35,17 @@ export function collectBundledExtensionManifestErrors(extensions: BundledExtensi
|
||||
`bundled extension '${extension.id}' manifest invalid | openclaw.install.npmSpec must be a non-empty string`,
|
||||
);
|
||||
}
|
||||
const minHostVersionError =
|
||||
install?.minHostVersion === undefined ||
|
||||
parseMinHostVersionRequirement(install.minHostVersion)
|
||||
const minHostVersionCheck =
|
||||
install?.minHostVersion === undefined
|
||||
? null
|
||||
: MIN_HOST_VERSION_FORMAT;
|
||||
: checkMinHostVersion({
|
||||
currentVersion: "0.0.0",
|
||||
minHostVersion: install.minHostVersion,
|
||||
});
|
||||
const minHostVersionError =
|
||||
minHostVersionCheck && !minHostVersionCheck.ok && minHostVersionCheck.kind === "invalid"
|
||||
? minHostVersionCheck.error
|
||||
: null;
|
||||
if (minHostVersionError) {
|
||||
errors.push(`bundled extension '${extension.id}' manifest invalid | ${minHostVersionError}`);
|
||||
}
|
||||
|
||||
@@ -6,9 +6,8 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
import type { createJiti } from "jiti";
|
||||
import { buildChannelConfigSchema } from "../src/channels/plugins/config-schema.js";
|
||||
import {
|
||||
buildPluginLoaderAliasMap,
|
||||
buildPluginLoaderJitiOptions,
|
||||
resolvePluginSdkAliasFile,
|
||||
resolvePluginSdkScopedAliasMap,
|
||||
} from "../src/plugins/sdk-alias.js";
|
||||
|
||||
type CreateJiti = typeof createJiti;
|
||||
@@ -152,19 +151,7 @@ export async function loadChannelConfigSurfaceModule(
|
||||
};
|
||||
const loadViaJiti = (candidatePath: string) => {
|
||||
const resolvedPath = path.resolve(candidatePath);
|
||||
const pluginSdkAlias = resolvePluginSdkAliasFile({
|
||||
srcFile: "root-alias.cjs",
|
||||
distFile: "root-alias.cjs",
|
||||
modulePath: resolvedPath,
|
||||
pluginSdkResolution: "src",
|
||||
});
|
||||
const aliasMap = {
|
||||
...(pluginSdkAlias ? { "openclaw/plugin-sdk": pluginSdkAlias } : {}),
|
||||
...resolvePluginSdkScopedAliasMap({
|
||||
modulePath: resolvedPath,
|
||||
pluginSdkResolution: "src",
|
||||
}),
|
||||
};
|
||||
const aliasMap = buildPluginLoaderAliasMap(resolvedPath, "", undefined, "src");
|
||||
const jiti = loadCreateJitiLoaderFactory()(import.meta.url, {
|
||||
...buildPluginLoaderJitiOptions(aliasMap),
|
||||
interopDefault: true,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env node
|
||||
// Plugin Boundary Report script supports OpenClaw repository automation.
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { existsSync, lstatSync, readdirSync, readFileSync } from "node:fs";
|
||||
import { join, relative, resolve } from "node:path";
|
||||
@@ -10,7 +9,7 @@ import {
|
||||
reservedBundledPluginSdkEntrypoints,
|
||||
supportedBundledFacadeSdkEntrypoints,
|
||||
} from "../src/plugin-sdk/entrypoints.ts";
|
||||
import { PLUGIN_COMPAT_RECORDS } from "../src/plugins/compat/registry.ts";
|
||||
import { listPluginCompatRecords } from "../src/plugins/compat/registry.ts";
|
||||
import type { PluginCompatRecord } from "../src/plugins/compat/types.ts";
|
||||
|
||||
const REPO_ROOT = process.cwd();
|
||||
@@ -374,7 +373,8 @@ function collectCompatDebt(
|
||||
today = new Date(),
|
||||
options: { includeReferenceFiles?: boolean } = {},
|
||||
): CompatDebtRecord[] {
|
||||
return PLUGIN_COMPAT_RECORDS.filter((record) => record.status === "deprecated")
|
||||
return listPluginCompatRecords()
|
||||
.filter((record) => record.status === "deprecated")
|
||||
.map((record) => {
|
||||
const tokens = extractCompatTokens(record);
|
||||
const references =
|
||||
@@ -389,7 +389,7 @@ function collectCompatDebt(
|
||||
owner: record.owner,
|
||||
status: record.status,
|
||||
removeAfter: record.removeAfter,
|
||||
replacement: record.replacement,
|
||||
replacement: record.replacement as string,
|
||||
docsPath: record.docsPath,
|
||||
surfaces: record.surfaces,
|
||||
tokens,
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
initializeGlobalHookRunner,
|
||||
resetGlobalHookRunner,
|
||||
} from "../plugins/hook-runner-global.js";
|
||||
import { addTestHook, createMockPluginRegistry } from "../plugins/hooks.test-helpers.js";
|
||||
import { addTestHook, createMockPluginRegistry } from "../plugins/hooks.test-fixtures.js";
|
||||
import { patchPluginSessionExtension } from "../plugins/host-hook-state.js";
|
||||
import { createEmptyPluginRegistry } from "../plugins/registry.js";
|
||||
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
initializeGlobalHookRunner,
|
||||
resetGlobalHookRunner,
|
||||
} from "../plugins/hook-runner-global.js";
|
||||
import { createMockPluginRegistry } from "../plugins/hooks.test-helpers.js";
|
||||
import { createMockPluginRegistry } from "../plugins/hooks.test-fixtures.js";
|
||||
import "./test-helpers/fast-bash-tools.js";
|
||||
import "./test-helpers/fast-coding-tools.js";
|
||||
import "./test-helpers/fast-openclaw-tools.js";
|
||||
|
||||
@@ -1,281 +0,0 @@
|
||||
/** E2E proof for CLI runner bundle-MCP subprocess execution. */
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { CliBackendConfig } from "../config/types.js";
|
||||
import { captureEnv, deleteTestEnvValue, setTestEnvValue } from "../test-utils/env.js";
|
||||
import {
|
||||
writeBundleProbeMcpServer,
|
||||
writeClaudeBundle,
|
||||
writeFakeClaudeCli,
|
||||
writeFakeClaudeLiveCli,
|
||||
} from "./bundle-mcp.test-harness.js";
|
||||
import type {
|
||||
CliPreparedBackend,
|
||||
PreparedCliRunContext,
|
||||
RunCliAgentParams,
|
||||
} from "./cli-runner/types.js";
|
||||
|
||||
// This e2e spins a real stdio MCP server plus a spawned CLI process. Keep the
|
||||
// proof focused on bundle MCP config generation and subprocess execution; the
|
||||
// full runCliAgent prepare graph has dedicated unit coverage and is expensive
|
||||
// in cold Linux workers.
|
||||
const E2E_TIMEOUT_MS = 30_000;
|
||||
|
||||
type BundleMcpFixture = {
|
||||
config: OpenClawConfig;
|
||||
envSnapshot: ReturnType<typeof captureEnv>;
|
||||
fakeClaudePath: string;
|
||||
fakeClaudePidPath?: string;
|
||||
pluginRoot: string;
|
||||
sessionFile: string;
|
||||
tempHome: string;
|
||||
workspaceDir: string;
|
||||
};
|
||||
|
||||
function isProcessAlive(pid: number): boolean {
|
||||
try {
|
||||
process.kill(pid, 0);
|
||||
return true;
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.ErrnoException).code === "ESRCH") {
|
||||
return false;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function resetBundleMcpPluginState() {
|
||||
// Bundle MCP setup caches plugin discovery; reset between temp plugin roots.
|
||||
const { resetPluginLoaderTestStateForTest } = await import("../plugins/loader.test-fixtures.js");
|
||||
const { clearPluginSetupRegistryCache } = await import("../plugins/setup-registry.js");
|
||||
resetPluginLoaderTestStateForTest();
|
||||
clearPluginSetupRegistryCache();
|
||||
}
|
||||
|
||||
async function createBundleMcpFixture(params: {
|
||||
liveSession?: boolean;
|
||||
tempPrefix: string;
|
||||
}): Promise<BundleMcpFixture> {
|
||||
// Fixture creates a real temp plugin + MCP server + fake CLI binary, but keeps
|
||||
// it isolated from persisted plugin registry state.
|
||||
await resetBundleMcpPluginState();
|
||||
const envSnapshot = captureEnv([
|
||||
"HOME",
|
||||
"USERPROFILE",
|
||||
"OPENCLAW_HOME",
|
||||
"OPENCLAW_STATE_DIR",
|
||||
"OPENCLAW_DISABLE_PERSISTED_PLUGIN_REGISTRY",
|
||||
]);
|
||||
const tempHome = await fs.mkdtemp(path.join(os.tmpdir(), params.tempPrefix));
|
||||
setTestEnvValue("HOME", tempHome);
|
||||
setTestEnvValue("USERPROFILE", tempHome);
|
||||
deleteTestEnvValue("OPENCLAW_HOME");
|
||||
deleteTestEnvValue("OPENCLAW_STATE_DIR");
|
||||
setTestEnvValue("OPENCLAW_DISABLE_PERSISTED_PLUGIN_REGISTRY", "1");
|
||||
|
||||
const workspaceDir = path.join(tempHome, "workspace");
|
||||
const sessionFile = path.join(tempHome, "session.jsonl");
|
||||
const binDir = path.join(tempHome, "bin");
|
||||
const serverScriptPath = path.join(tempHome, "mcp", "bundle-probe.mjs");
|
||||
const fakeClaudePath = path.join(
|
||||
binDir,
|
||||
params.liveSession ? "fake-live-claude.mjs" : "fake-claude.mjs",
|
||||
);
|
||||
const fakeClaudePidPath = params.liveSession
|
||||
? path.join(tempHome, "fake-live-claude.pid")
|
||||
: undefined;
|
||||
const pluginRoot = path.join(tempHome, ".openclaw", "extensions", "bundle-probe");
|
||||
await fs.mkdir(workspaceDir, { recursive: true });
|
||||
await writeBundleProbeMcpServer(serverScriptPath);
|
||||
if (params.liveSession) {
|
||||
await writeFakeClaudeLiveCli({ filePath: fakeClaudePath, pidPath: fakeClaudePidPath });
|
||||
} else {
|
||||
await writeFakeClaudeCli(fakeClaudePath);
|
||||
}
|
||||
await writeClaudeBundle({ pluginRoot, serverScriptPath });
|
||||
|
||||
const config: OpenClawConfig = {
|
||||
agents: {
|
||||
defaults: {
|
||||
workspace: workspaceDir,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
load: { paths: [pluginRoot] },
|
||||
entries: {
|
||||
"bundle-probe": { enabled: true },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
config,
|
||||
envSnapshot,
|
||||
fakeClaudePath,
|
||||
...(fakeClaudePidPath ? { fakeClaudePidPath } : {}),
|
||||
pluginRoot,
|
||||
sessionFile,
|
||||
tempHome,
|
||||
workspaceDir,
|
||||
};
|
||||
}
|
||||
|
||||
function buildTestBackend(params: {
|
||||
commandPath: string;
|
||||
liveSession?: "claude-stdio";
|
||||
}): CliBackendConfig {
|
||||
return {
|
||||
command: "node",
|
||||
args: [params.commandPath],
|
||||
input: "stdin",
|
||||
output: "jsonl",
|
||||
clearEnv: [],
|
||||
...(params.liveSession ? { liveSession: params.liveSession } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
async function prepareBundleMcpExecutionContext(params: {
|
||||
backend: CliBackendConfig;
|
||||
config: OpenClawConfig;
|
||||
model: string;
|
||||
prompt: string;
|
||||
runId: string;
|
||||
sessionFile: string;
|
||||
sessionId: string;
|
||||
workspaceDir: string;
|
||||
}): Promise<PreparedCliRunContext> {
|
||||
// Exercise bundle MCP config preparation while bypassing unrelated full
|
||||
// runCliAgent context assembly.
|
||||
const { prepareCliBundleMcpConfig } = await import("./cli-runner/bundle-mcp.js");
|
||||
const preparedBackend = (await prepareCliBundleMcpConfig({
|
||||
enabled: true,
|
||||
mode: "claude-config-file",
|
||||
backend: params.backend,
|
||||
workspaceDir: params.workspaceDir,
|
||||
config: params.config,
|
||||
})) as CliPreparedBackend;
|
||||
const runParams: RunCliAgentParams = {
|
||||
sessionId: params.sessionId,
|
||||
sessionFile: params.sessionFile,
|
||||
workspaceDir: params.workspaceDir,
|
||||
config: params.config,
|
||||
prompt: params.prompt,
|
||||
provider: "claude-cli",
|
||||
model: params.model,
|
||||
timeoutMs: 20_000,
|
||||
runId: params.runId,
|
||||
};
|
||||
|
||||
return {
|
||||
params: runParams,
|
||||
started: Date.now(),
|
||||
workspaceDir: params.workspaceDir,
|
||||
cwd: params.workspaceDir,
|
||||
backendResolved: {
|
||||
id: "claude-cli",
|
||||
config: params.backend,
|
||||
bundleMcp: true,
|
||||
bundleMcpMode: "claude-config-file",
|
||||
},
|
||||
preparedBackend,
|
||||
reusableCliSession: { mode: "none" },
|
||||
hadSessionFile: false,
|
||||
contextEngineConfig: params.config,
|
||||
modelId: params.model,
|
||||
normalizedModel: params.model,
|
||||
systemPrompt: "Bundle MCP e2e test prompt.",
|
||||
systemPromptReport: {} as PreparedCliRunContext["systemPromptReport"],
|
||||
claudeSkillsPluginArgs: [],
|
||||
bootstrapPromptWarningLines: [],
|
||||
authEpochVersion: 1,
|
||||
};
|
||||
}
|
||||
|
||||
async function cleanupFixture(fixture: BundleMcpFixture): Promise<void> {
|
||||
await fs.rm(fixture.tempHome, { recursive: true, force: true });
|
||||
fixture.envSnapshot.restore();
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
await resetBundleMcpPluginState();
|
||||
});
|
||||
|
||||
describe("CLI bundle MCP e2e", () => {
|
||||
it(
|
||||
"routes enabled bundle MCP config into the claude-cli backend and executes the tool",
|
||||
{ timeout: E2E_TIMEOUT_MS },
|
||||
async () => {
|
||||
const { executePreparedCliRun } = await import("./cli-runner/execute.js");
|
||||
const fixture = await createBundleMcpFixture({
|
||||
tempPrefix: "openclaw-cli-bundle-mcp-",
|
||||
});
|
||||
const context = await prepareBundleMcpExecutionContext({
|
||||
backend: buildTestBackend({ commandPath: fixture.fakeClaudePath }),
|
||||
config: fixture.config,
|
||||
model: "test-bundle",
|
||||
prompt: "Use your configured MCP tools and report the bundle probe text.",
|
||||
runId: "bundle-mcp-e2e",
|
||||
sessionFile: fixture.sessionFile,
|
||||
sessionId: "session:test",
|
||||
workspaceDir: fixture.workspaceDir,
|
||||
});
|
||||
|
||||
try {
|
||||
const result = await executePreparedCliRun(context);
|
||||
|
||||
expect(result.text).toContain("BUNDLE MCP OK FROM-BUNDLE");
|
||||
} finally {
|
||||
await context.preparedBackend.cleanup?.();
|
||||
await cleanupFixture(fixture);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
it(
|
||||
"exits one-shot Claude live-session runs and closes the live process",
|
||||
{ timeout: E2E_TIMEOUT_MS },
|
||||
async () => {
|
||||
const { executePreparedCliRun } = await import("./cli-runner/execute.js");
|
||||
const { closeClaudeLiveSessionForContext } =
|
||||
await import("./cli-runner/claude-live-session.js");
|
||||
const fixture = await createBundleMcpFixture({
|
||||
liveSession: true,
|
||||
tempPrefix: "openclaw-cli-live-cleanup-",
|
||||
});
|
||||
const context = await prepareBundleMcpExecutionContext({
|
||||
backend: buildTestBackend({
|
||||
commandPath: fixture.fakeClaudePath,
|
||||
liveSession: "claude-stdio",
|
||||
}),
|
||||
config: fixture.config,
|
||||
model: "test-live-bundle",
|
||||
prompt: "Use your configured MCP tools and report the bundle probe text.",
|
||||
runId: "bundle-mcp-live-cleanup-e2e",
|
||||
sessionFile: fixture.sessionFile,
|
||||
sessionId: "session:test-live-cleanup",
|
||||
workspaceDir: fixture.workspaceDir,
|
||||
});
|
||||
|
||||
try {
|
||||
const result = await executePreparedCliRun(context);
|
||||
await closeClaudeLiveSessionForContext(context);
|
||||
|
||||
expect(result.text).toContain("LIVE BUNDLE MCP OK FROM-BUNDLE");
|
||||
expect(fixture.fakeClaudePidPath).toBeDefined();
|
||||
const fakeClaudePid = Number.parseInt(
|
||||
await fs.readFile(fixture.fakeClaudePidPath!, "utf-8"),
|
||||
10,
|
||||
);
|
||||
expect(Number.isFinite(fakeClaudePid)).toBe(true);
|
||||
expect(isProcessAlive(fakeClaudePid)).toBe(false);
|
||||
} finally {
|
||||
await closeClaudeLiveSessionForContext(context);
|
||||
await context.preparedBackend.cleanup?.();
|
||||
await cleanupFixture(fixture);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
@@ -22,7 +22,10 @@ import type {
|
||||
McpLoopbackRequestContext,
|
||||
} from "../../gateway/mcp-grant-store.js";
|
||||
import { getGlobalHookRunner } from "../../plugins/hook-runner-global.js";
|
||||
import { clearMemoryPluginState, registerMemoryPromptSection } from "../../plugins/memory-state.js";
|
||||
import {
|
||||
clearMemoryPluginState,
|
||||
registerMemoryPromptSection,
|
||||
} from "../../plugins/memory-state.test-fixtures.js";
|
||||
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
||||
import {
|
||||
createChannelTestPluginBase,
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
initializeGlobalHookRunner,
|
||||
resetGlobalHookRunner,
|
||||
} from "../../../plugins/hook-runner-global.js";
|
||||
import { createHookRunnerWithRegistry } from "../../../plugins/hooks.test-helpers.js";
|
||||
import { createHookRunnerWithRegistry } from "../../../plugins/hooks.test-fixtures.js";
|
||||
import { withEnvAsync } from "../../../test-utils/env.js";
|
||||
import { wrapStreamFnWithDiagnosticModelCallEvents } from "./attempt.model-diagnostic-events.js";
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import { buildMemorySystemPromptAddition } from "../../../context-engine/delegat
|
||||
import {
|
||||
clearMemoryPluginState,
|
||||
registerMemoryPromptSection,
|
||||
} from "../../../plugins/memory-state.js";
|
||||
} from "../../../plugins/memory-state.test-fixtures.js";
|
||||
import {
|
||||
addSubagentRunForTests,
|
||||
leasePendingAgentSteeringItems,
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
// Embedded system prompt tests cover prompt assembly for provider guidance,
|
||||
// delegation mode, workspace-only safety, memory sections, and active processes.
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { clearMemoryPluginState, registerMemoryPromptSection } from "../../plugins/memory-state.js";
|
||||
import {
|
||||
clearMemoryPluginState,
|
||||
registerMemoryPromptSection,
|
||||
} from "../../plugins/memory-state.test-fixtures.js";
|
||||
import type { AgentSession } from "../sessions/index.js";
|
||||
import { applySystemPromptToSession, buildEmbeddedSystemPrompt } from "./system-prompt.js";
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { createInlineCodeState } from "../../packages/markdown-core/src/code-spans.js";
|
||||
import { createHookRunner } from "../plugins/hooks.js";
|
||||
import { createMockPluginRegistry, TEST_PLUGIN_AGENT_CTX } from "../plugins/hooks.test-helpers.js";
|
||||
import { createMockPluginRegistry, TEST_PLUGIN_AGENT_CTX } from "../plugins/hooks.test-fixtures.js";
|
||||
import { handleAgentEnd, handleAgentStart } from "./embedded-agent-subscribe.handlers.lifecycle.js";
|
||||
import type { EmbeddedAgentSubscribeContext } from "./embedded-agent-subscribe.handlers.types.js";
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
initializeGlobalHookRunner,
|
||||
resetGlobalHookRunner,
|
||||
} from "../../plugins/hook-runner-global.js";
|
||||
import { createMockPluginRegistry } from "../../plugins/hooks.test-helpers.js";
|
||||
import { createMockPluginRegistry } from "../../plugins/hooks.test-fixtures.js";
|
||||
import { patchPluginSessionExtension } from "../../plugins/host-hook-state.js";
|
||||
import { createEmptyPluginRegistry } from "../../plugins/registry-empty.js";
|
||||
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
initializeGlobalHookRunner,
|
||||
resetGlobalHookRunner,
|
||||
} from "../../plugins/hook-runner-global.js";
|
||||
import { createMockPluginRegistry } from "../../plugins/hooks.test-helpers.js";
|
||||
import { createMockPluginRegistry } from "../../plugins/hooks.test-fixtures.js";
|
||||
import { resolveAgentHarnessBeforePromptBuildResult } from "./prompt-compaction-hook-helpers.js";
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -14,13 +14,9 @@ import { resetLogger, setLoggerOverride } from "../logging/logger.js";
|
||||
import { createWarnLogCapture } from "../logging/test-helpers/warn-log-capture.js";
|
||||
import {
|
||||
clearCurrentPluginMetadataSnapshot,
|
||||
resolvePluginMetadataControlPlaneFingerprint,
|
||||
setCurrentPluginMetadataSnapshot,
|
||||
} from "../plugins/current-plugin-metadata-snapshot.js";
|
||||
import { resolveInstalledPluginIndexPolicyHash } from "../plugins/installed-plugin-index-policy.js";
|
||||
import type { InstalledPluginIndex } from "../plugins/installed-plugin-index.js";
|
||||
import { loadPluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
|
||||
import type { PluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.types.js";
|
||||
import { CommandLaneTaskTimeoutError } from "../process/command-queue.js";
|
||||
import { AUTH_STORE_VERSION } from "./auth-profiles/constants.js";
|
||||
import type { AuthProfileStore } from "./auth-profiles/types.js";
|
||||
@@ -229,68 +225,6 @@ function setDefaultPluginMetadataSnapshot(): void {
|
||||
});
|
||||
}
|
||||
|
||||
function createModelNormalizerSnapshot(params: {
|
||||
manifestHash: string;
|
||||
prefix: string;
|
||||
}): PluginMetadataSnapshot {
|
||||
// Builds a process-stable plugin metadata snapshot with one model normalizer
|
||||
// so fallback can prove manifest-policy cache invalidation.
|
||||
const policyHash = resolveInstalledPluginIndexPolicyHash({});
|
||||
const index: InstalledPluginIndex = {
|
||||
version: 1,
|
||||
hostContractVersion: "test-host",
|
||||
compatRegistryVersion: "test-compat",
|
||||
migrationVersion: 1,
|
||||
policyHash,
|
||||
generatedAtMs: 0,
|
||||
installRecords: {},
|
||||
plugins: [
|
||||
{
|
||||
pluginId: "fallback-normalizer",
|
||||
manifestPath: `/tmp/fallback-normalizer-${params.manifestHash}/openclaw.plugin.json`,
|
||||
manifestHash: params.manifestHash,
|
||||
source: `/tmp/fallback-normalizer-${params.manifestHash}/index.ts`,
|
||||
rootDir: `/tmp/fallback-normalizer-${params.manifestHash}`,
|
||||
origin: "global",
|
||||
enabled: true,
|
||||
startup: {
|
||||
sidecar: false,
|
||||
memory: false,
|
||||
deferConfiguredChannelFullLoadUntilAfterListen: false,
|
||||
agentHarnesses: [],
|
||||
},
|
||||
compat: [],
|
||||
},
|
||||
],
|
||||
diagnostics: [],
|
||||
};
|
||||
return {
|
||||
policyHash,
|
||||
configFingerprint: resolvePluginMetadataControlPlaneFingerprint(
|
||||
{},
|
||||
{
|
||||
env: process.env,
|
||||
index,
|
||||
policyHash,
|
||||
},
|
||||
),
|
||||
index,
|
||||
registryDiagnostics: [],
|
||||
plugins: [
|
||||
{
|
||||
id: "fallback-normalizer",
|
||||
modelIdNormalization: {
|
||||
providers: {
|
||||
demo: {
|
||||
prefixWhenBare: params.prefix,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
} as unknown as PluginMetadataSnapshot;
|
||||
}
|
||||
|
||||
afterEach(resetModelFallbackTestState);
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -3129,54 +3063,6 @@ describe("runWithModelFallback", () => {
|
||||
).toEqual([{ provider: "ollama", model: "llama3" }]);
|
||||
});
|
||||
|
||||
it("does not reuse fallback candidate cache entries across manifest normalization snapshots", () => {
|
||||
const cfg = makeCfg({
|
||||
agents: {
|
||||
defaults: {
|
||||
model: {
|
||||
fallbacks: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
setCurrentPluginMetadataSnapshot(
|
||||
createModelNormalizerSnapshot({
|
||||
manifestHash: "alpha",
|
||||
prefix: "alpha",
|
||||
}),
|
||||
{ config: {}, env: process.env },
|
||||
);
|
||||
expect(
|
||||
testing.resolveFallbackCandidates({
|
||||
cfg,
|
||||
provider: "demo",
|
||||
model: "demo-model",
|
||||
fallbacksOverride: [],
|
||||
}),
|
||||
).toEqual([{ provider: "demo", model: "alpha/demo-model" }]);
|
||||
|
||||
setCurrentPluginMetadataSnapshot(
|
||||
createModelNormalizerSnapshot({
|
||||
manifestHash: "bravo",
|
||||
prefix: "bravo",
|
||||
}),
|
||||
{ config: {}, env: process.env },
|
||||
);
|
||||
expect(
|
||||
testing.resolveFallbackCandidates({
|
||||
cfg,
|
||||
provider: "demo",
|
||||
model: "demo-model",
|
||||
fallbacksOverride: [],
|
||||
}),
|
||||
).toEqual([{ provider: "demo", model: "bravo/demo-model" }]);
|
||||
} finally {
|
||||
setDefaultPluginMetadataSnapshot();
|
||||
}
|
||||
});
|
||||
|
||||
it("defaults provider/model when missing (regression #946)", () => {
|
||||
const cfg = makeCfg({
|
||||
agents: {
|
||||
|
||||
@@ -1,82 +1,9 @@
|
||||
// Verifies model-selection CLI provider detection from plugin metadata.
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/types.js";
|
||||
import {
|
||||
clearCurrentPluginMetadataSnapshot,
|
||||
resolvePluginMetadataControlPlaneFingerprint,
|
||||
setCurrentPluginMetadataSnapshot,
|
||||
} from "../plugins/current-plugin-metadata-snapshot.js";
|
||||
import { resolveInstalledPluginIndexPolicyHash } from "../plugins/installed-plugin-index-policy.js";
|
||||
import type { InstalledPluginIndex } from "../plugins/installed-plugin-index.js";
|
||||
import type { PluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
|
||||
import { testing as setupRegistryRuntimeTesting } from "../plugins/setup-registry.runtime.js";
|
||||
import { isCliProvider } from "./model-selection-cli.js";
|
||||
|
||||
function setCliBackendMetadataSnapshot(cliBackends: string[]) {
|
||||
// Builds a minimal current plugin metadata snapshot so isCliProvider can use
|
||||
// descriptor metadata without loading setup runtime modules.
|
||||
const policyHash = resolveInstalledPluginIndexPolicyHash({});
|
||||
const index: InstalledPluginIndex = {
|
||||
version: 1,
|
||||
hostContractVersion: "test-host",
|
||||
compatRegistryVersion: "test-compat",
|
||||
migrationVersion: 1,
|
||||
policyHash,
|
||||
generatedAtMs: 0,
|
||||
installRecords: {},
|
||||
plugins: [
|
||||
{
|
||||
pluginId: "anthropic",
|
||||
manifestPath: "/tmp/anthropic/openclaw.plugin.json",
|
||||
manifestHash: "test-manifest",
|
||||
source: "/tmp/anthropic/index.ts",
|
||||
rootDir: "/tmp/anthropic",
|
||||
origin: "bundled",
|
||||
enabled: true,
|
||||
startup: {
|
||||
sidecar: false,
|
||||
memory: false,
|
||||
deferConfiguredChannelFullLoadUntilAfterListen: false,
|
||||
agentHarnesses: [],
|
||||
},
|
||||
compat: [],
|
||||
},
|
||||
],
|
||||
diagnostics: [],
|
||||
};
|
||||
const snapshot = {
|
||||
policyHash,
|
||||
configFingerprint: resolvePluginMetadataControlPlaneFingerprint(
|
||||
{},
|
||||
{
|
||||
env: process.env,
|
||||
index,
|
||||
policyHash,
|
||||
},
|
||||
),
|
||||
index,
|
||||
plugins: [
|
||||
{
|
||||
id: "anthropic",
|
||||
origin: "bundled",
|
||||
cliBackends,
|
||||
},
|
||||
],
|
||||
} as unknown as PluginMetadataSnapshot;
|
||||
setCurrentPluginMetadataSnapshot(snapshot, { config: {}, env: process.env });
|
||||
}
|
||||
|
||||
describe("isCliProvider", () => {
|
||||
beforeEach(() => {
|
||||
setupRegistryRuntimeTesting.resetDescriptorCache();
|
||||
setCliBackendMetadataSnapshot(["claude-cli"]);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
clearCurrentPluginMetadataSnapshot();
|
||||
setupRegistryRuntimeTesting.resetDescriptorCache();
|
||||
});
|
||||
|
||||
it("returns true for setup-registered cli backends", () => {
|
||||
expect(isCliProvider("claude-cli", {} as OpenClawConfig)).toBe(true);
|
||||
});
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { setBundledPluginsDirOverrideForTest } from "../plugins/bundled-dir.js";
|
||||
import {
|
||||
clearCurrentPluginMetadataSnapshot,
|
||||
getCurrentPluginMetadataSnapshot,
|
||||
@@ -170,7 +169,7 @@ describe("optional media tool factory planning", () => {
|
||||
workflow: { "1": { inputs: {} } },
|
||||
promptNodeId: "1",
|
||||
});
|
||||
setBundledPluginsDirOverrideForTest(path.join(process.cwd(), "extensions"));
|
||||
vi.stubEnv("OPENCLAW_BUNDLED_PLUGINS_DIR", path.join(process.cwd(), "extensions"));
|
||||
legacyComfyToolNames = (
|
||||
await createOpenClawToolsForTest({
|
||||
config,
|
||||
@@ -181,7 +180,7 @@ describe("optional media tool factory planning", () => {
|
||||
clearCurrentPluginMetadataSnapshot();
|
||||
resetPluginRuntimeStateForTest();
|
||||
clearSecretsRuntimeSnapshot();
|
||||
setBundledPluginsDirOverrideForTest(undefined);
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -193,7 +192,6 @@ describe("optional media tool factory planning", () => {
|
||||
clearCurrentPluginMetadataSnapshot();
|
||||
resetPluginRuntimeStateForTest();
|
||||
clearSecretsRuntimeSnapshot();
|
||||
setBundledPluginsDirOverrideForTest(undefined);
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
|
||||
@@ -238,7 +236,7 @@ describe("optional media tool factory planning", () => {
|
||||
it("does not plan media factories from workspace-scoped metadata without workspace context", () => {
|
||||
// Workspace snapshots are process-local facts and must not leak to unrelated runs.
|
||||
const config: OpenClawConfig = {};
|
||||
setBundledPluginsDirOverrideForTest("/nonexistent/bundled/plugins");
|
||||
vi.stubEnv("OPENCLAW_DISABLE_BUNDLED_PLUGINS", "1");
|
||||
installSnapshot(
|
||||
config,
|
||||
[
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
// Verifies runtime plugin loading can reuse a compatible gateway startup registry.
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createEmptyPluginRegistry } from "../plugins/registry-empty.js";
|
||||
import type { PluginRegistry } from "../plugins/registry-types.js";
|
||||
import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
getCurrentPluginMetadataSnapshot: vi.fn(),
|
||||
loadOpenClawPlugins: vi.fn<typeof import("../plugins/loader.js").loadOpenClawPlugins>(),
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/current-plugin-metadata-snapshot.js", () => ({
|
||||
getCurrentPluginMetadataSnapshot: mocks.getCurrentPluginMetadataSnapshot,
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/loader.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../plugins/loader.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadOpenClawPlugins: (...args: Parameters<typeof mocks.loadOpenClawPlugins>) =>
|
||||
mocks.loadOpenClawPlugins(...args),
|
||||
};
|
||||
});
|
||||
|
||||
const [{ ensureRuntimePluginsLoaded }, { clearPluginLoaderCache, testing }] = await Promise.all([
|
||||
import("./runtime-plugins.js"),
|
||||
import("../plugins/loader.js"),
|
||||
]);
|
||||
|
||||
function createRegistryWithPlugin(pluginId: string): PluginRegistry {
|
||||
// Minimal active registry carrying just enough plugin identity for reuse checks.
|
||||
const registry = createEmptyPluginRegistry();
|
||||
registry.plugins.push({
|
||||
id: pluginId,
|
||||
status: "loaded",
|
||||
} as never);
|
||||
return registry;
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
clearPluginLoaderCache();
|
||||
resetPluginRuntimeStateForTest();
|
||||
mocks.getCurrentPluginMetadataSnapshot.mockReset();
|
||||
mocks.loadOpenClawPlugins.mockReset();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
clearPluginLoaderCache();
|
||||
resetPluginRuntimeStateForTest();
|
||||
});
|
||||
|
||||
describe("ensureRuntimePluginsLoaded registry reuse", () => {
|
||||
it("reuses the compatible gateway startup registry on the dispatch caller path", () => {
|
||||
// Matching cache key plus gateway-bindable mode means no second plugin load.
|
||||
const config = { plugins: { allow: ["telegram"] } };
|
||||
const activeRegistry = createRegistryWithPlugin("telegram");
|
||||
activeRegistry.coreGatewayMethodNames = ["sessions.get", "sessions.list"];
|
||||
const startupLoadOptions = {
|
||||
config,
|
||||
activationSourceConfig: config,
|
||||
autoEnabledReasons: {},
|
||||
workspaceDir: "/tmp/workspace",
|
||||
onlyPluginIds: ["telegram"],
|
||||
coreGatewayMethodNames: ["sessions.get", "sessions.list"],
|
||||
runtimeOptions: {
|
||||
allowGatewaySubagentBinding: true,
|
||||
},
|
||||
preferBuiltPluginArtifacts: true,
|
||||
};
|
||||
const { cacheKey } = testing.resolvePluginLoadCacheContext(startupLoadOptions);
|
||||
setActivePluginRegistry(activeRegistry, cacheKey, "gateway-bindable", "/tmp/workspace");
|
||||
mocks.getCurrentPluginMetadataSnapshot.mockReturnValue({
|
||||
startup: {
|
||||
pluginIds: ["telegram"],
|
||||
},
|
||||
});
|
||||
mocks.loadOpenClawPlugins.mockImplementation(() => {
|
||||
throw new Error("dispatch should reuse the active gateway startup registry");
|
||||
});
|
||||
|
||||
ensureRuntimePluginsLoaded({
|
||||
config,
|
||||
workspaceDir: "/tmp/workspace",
|
||||
});
|
||||
|
||||
expect(mocks.getCurrentPluginMetadataSnapshot).toHaveBeenCalledWith({
|
||||
config,
|
||||
workspaceDir: "/tmp/workspace",
|
||||
});
|
||||
expect(mocks.loadOpenClawPlugins).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,10 @@
|
||||
// System prompt memory tests cover opt-out behavior when context engines own
|
||||
// memory prompt assembly for a run.
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { clearMemoryPluginState, registerMemoryPromptSection } from "../plugins/memory-state.js";
|
||||
import {
|
||||
clearMemoryPluginState,
|
||||
registerMemoryPromptSection,
|
||||
} from "../plugins/memory-state.test-fixtures.js";
|
||||
import { buildAgentSystemPrompt } from "./system-prompt.js";
|
||||
|
||||
describe("buildAgentSystemPrompt memory guidance", () => {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { clearPluginLoaderCache } from "../../plugins/loader.js";
|
||||
import { clearPluginLoaderCache } from "../../plugins/loader.test-fixtures.js";
|
||||
import { createEmptyPluginRegistry } from "../../plugins/registry.js";
|
||||
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { clearRuntimeAuthProfileStoreSnapshots } from "../agents/auth-profiles.j
|
||||
import { clearSessionStoreCacheForTest } from "../config/sessions.js";
|
||||
import { resetSystemEventsForTest } from "../infra/system-events.js";
|
||||
import { createEmptyPluginRegistry } from "../plugins/registry-empty.js";
|
||||
import type { PluginProviderRegistration } from "../plugins/registry.js";
|
||||
import type { PluginRegistry } from "../plugins/registry.js";
|
||||
import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
import type { ProviderPlugin } from "../plugins/types.js";
|
||||
import { resetSkillsRefreshForTest } from "../skills/runtime/refresh.js";
|
||||
@@ -22,6 +22,8 @@ import {
|
||||
runReplyAgentMock,
|
||||
} from "./reply.directive.directive-behavior.e2e-mocks.js";
|
||||
|
||||
type PluginProviderRegistration = PluginRegistry["providers"][number];
|
||||
|
||||
const DEFAULT_TEST_MODEL_CATALOG: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
clearMemoryPluginState,
|
||||
registerMemoryCapability,
|
||||
type MemoryFlushPlanResolver,
|
||||
} from "../../plugins/memory-state.js";
|
||||
} from "../../plugins/memory-state.test-fixtures.js";
|
||||
import {
|
||||
runPreflightCompactionIfNeeded,
|
||||
setAgentRunnerMemoryTestDeps,
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
clearMemoryPluginState,
|
||||
registerMemoryCapability,
|
||||
type MemoryFlushPlanResolver,
|
||||
} from "../../plugins/memory-state.js";
|
||||
} from "../../plugins/memory-state.test-fixtures.js";
|
||||
import type { TemplateContext } from "../templating.js";
|
||||
import type { ReplyPayload } from "../types.js";
|
||||
import {
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
clearMemoryPluginState,
|
||||
registerMemoryCapability,
|
||||
type MemoryFlushPlanResolver,
|
||||
} from "../../plugins/memory-state.js";
|
||||
} from "../../plugins/memory-state.test-fixtures.js";
|
||||
import { GatewayDrainingError } from "../../process/command-queue.js";
|
||||
import { getReplyPayloadMetadata, type ReplyPayload } from "../reply-payload.js";
|
||||
import type { TemplateContext } from "../templating.js";
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { clearPluginCommands, registerPluginCommand } from "../../plugins/commands.js";
|
||||
import { createPluginRegistry } from "../../plugins/registry.js";
|
||||
import type { PluginRuntime } from "../../plugins/runtime/types.js";
|
||||
import { createBundledPluginRecord } from "../../plugins/status.test-helpers.js";
|
||||
import { createBundledPluginRecord } from "../../plugins/status.test-fixtures.js";
|
||||
import type { PluginCommandContext, PluginCommandHandler } from "../../plugins/types.js";
|
||||
import type { MsgContext } from "../templating.js";
|
||||
import { createDiagnosticsCommandHandler } from "./commands-diagnostics.js";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Tests dispatch-from-config reply dispatch integration and final payload routing.
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { clearAgentHarnesses } from "../../agents/harness/registry.js";
|
||||
import type { PluginHookReplyDispatchResult } from "../../plugins/hooks.js";
|
||||
import type { PluginHookReplyDispatchResult } from "../../plugins/hooks.test-fixtures.js";
|
||||
import { createInternalHookEventPayload } from "../../test-utils/internal-hook-event-payload.js";
|
||||
import { withReplyDispatcher } from "../dispatch-dispatcher.js";
|
||||
import { setReplyPayloadMetadata } from "../reply-payload.js";
|
||||
|
||||
@@ -6,8 +6,8 @@ import type { StuckSessionRecoveryOutcome } from "../../logging/diagnostic-sessi
|
||||
import type {
|
||||
PluginHookBeforeDispatchResult,
|
||||
PluginHookReplyDispatchResult,
|
||||
PluginTargetedInboundClaimOutcome,
|
||||
} from "../../plugins/hooks.js";
|
||||
} from "../../plugins/hook-types.js";
|
||||
import type { createHookRunner } from "../../plugins/hooks.js";
|
||||
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
||||
import {
|
||||
createChannelTestPluginBase,
|
||||
@@ -25,6 +25,9 @@ type AbortResult = {
|
||||
rejectionReason?: "finalizing";
|
||||
stoppedSubagents?: number;
|
||||
};
|
||||
type PluginTargetedInboundClaimOutcome = Awaited<
|
||||
ReturnType<ReturnType<typeof createHookRunner>["runInboundClaimForPluginOutcome"]>
|
||||
>;
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
isRoutableChannel: vi.fn((_channel: string | undefined) => true),
|
||||
|
||||
@@ -23,7 +23,7 @@ import type {
|
||||
AcpRuntimeTurnInput,
|
||||
} from "../../plugin-sdk/acp-runtime.js";
|
||||
import { clearPluginCommands, registerPluginCommand } from "../../plugins/commands.js";
|
||||
import type { PluginTargetedInboundClaimOutcome } from "../../plugins/hooks.js";
|
||||
import type { PluginTargetedInboundClaimOutcome } from "../../plugins/hooks.test-fixtures.js";
|
||||
import { setActivePluginRegistry } from "../../plugins/runtime.js";
|
||||
import {
|
||||
interruptSessionWorkAdmissions,
|
||||
|
||||
@@ -6,11 +6,8 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
import { resolveBundledChannelWorkspacePath } from "../../../../plugins/bundled-channel-runtime.js";
|
||||
import {
|
||||
resolvePluginRuntimeModulePath,
|
||||
resolvePluginRuntimeRecord,
|
||||
} from "../../../../plugins/runtime/runtime-plugin-boundary.js";
|
||||
import { listBundledChannelPluginMetadata } from "../../../../plugins/bundled-channel-runtime.js";
|
||||
import { resolvePluginRuntimeModulePath } from "../../../../plugins/runtime/runtime-plugin-boundary.js";
|
||||
|
||||
const REPO_ROOT = fileURLToPath(new URL("../../../../../", import.meta.url));
|
||||
|
||||
@@ -19,10 +16,11 @@ function resolveBundledChannelWorkspaceArtifactPath(
|
||||
entryBaseName: string,
|
||||
): string | null {
|
||||
const normalizedEntryBaseName = entryBaseName.replace(/\.(?:[cm]?js|ts)$/u, "");
|
||||
const pluginRoot = resolveBundledChannelWorkspacePath({
|
||||
const pluginRoot = listBundledChannelPluginMetadata({
|
||||
rootDir: REPO_ROOT,
|
||||
pluginId,
|
||||
});
|
||||
includeChannelConfigs: false,
|
||||
includeSyntheticChannelConfigs: false,
|
||||
}).find((metadata) => metadata.manifest.id === pluginId)?.rootDir;
|
||||
if (!pluginRoot) {
|
||||
return null;
|
||||
}
|
||||
@@ -37,15 +35,19 @@ function resolveBundledChannelWorkspaceArtifactPath(
|
||||
|
||||
function resolveBundledChannelContractArtifactUrl(pluginId: string, entryBaseName: string): string {
|
||||
const normalizedEntryBaseName = entryBaseName.replace(/\.(?:[cm]?js|ts)$/u, "");
|
||||
const record = resolvePluginRuntimeRecord(pluginId, () => {
|
||||
throw new Error(`missing bundled channel plugin '${pluginId}'`);
|
||||
});
|
||||
if (!record) {
|
||||
const metadata = listBundledChannelPluginMetadata({
|
||||
rootDir: REPO_ROOT,
|
||||
includeChannelConfigs: false,
|
||||
includeSyntheticChannelConfigs: false,
|
||||
}).find((entry) => entry.manifest.id === pluginId);
|
||||
if (!metadata) {
|
||||
throw new Error(`missing bundled channel plugin '${pluginId}'`);
|
||||
}
|
||||
const modulePath =
|
||||
resolvePluginRuntimeModulePath(record, normalizedEntryBaseName) ??
|
||||
resolveBundledChannelWorkspaceArtifactPath(pluginId, entryBaseName);
|
||||
resolvePluginRuntimeModulePath(
|
||||
{ rootDir: metadata.rootDir, source: metadata.source.built },
|
||||
normalizedEntryBaseName,
|
||||
) ?? resolveBundledChannelWorkspaceArtifactPath(pluginId, entryBaseName);
|
||||
if (!modulePath) {
|
||||
throw new Error(`missing ${entryBaseName} for bundled channel plugin '${pluginId}'`);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { vi } from "vitest";
|
||||
import { getRuntimeConfig } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { PluginInstallRecord } from "../config/types.plugins.js";
|
||||
import { createEmptyUninstallActions } from "../plugins/uninstall.js";
|
||||
import type { CliMockOutputRuntime } from "./test-runtime-capture.js";
|
||||
|
||||
type UnknownMock = Mock<(...args: unknown[]) => unknown>;
|
||||
@@ -27,6 +26,20 @@ type UpdateNpmInstalledHookPacksFn =
|
||||
(typeof import("../hooks/update.js"))["updateNpmInstalledHookPacks"];
|
||||
type PluginInstallRecordMap = Record<string, PluginInstallRecord>;
|
||||
|
||||
function createEmptyUninstallActions() {
|
||||
return {
|
||||
entry: false,
|
||||
install: false,
|
||||
allowlist: false,
|
||||
denylist: false,
|
||||
loadPath: false,
|
||||
memorySlot: false,
|
||||
contextEngineSlot: false,
|
||||
channelConfig: false,
|
||||
directory: false,
|
||||
};
|
||||
}
|
||||
|
||||
let mockInstalledPluginIndexInstallRecords: PluginInstallRecordMap = {};
|
||||
|
||||
function clonePluginInstallRecords(records: PluginInstallRecordMap): PluginInstallRecordMap {
|
||||
@@ -77,7 +90,6 @@ export const clearPluginRegistryLoadCache: UnknownMock = vi.fn();
|
||||
export const applyExclusiveSlotSelection: UnknownMock = vi.fn();
|
||||
export const planPluginUninstall: UnknownMock = vi.fn();
|
||||
export const applyPluginUninstallDirectoryRemoval: AsyncUnknownMock = vi.fn();
|
||||
const uninstallPlugin: AsyncUnknownMock = vi.fn();
|
||||
export const updateNpmInstalledPlugins: Mock<UpdateNpmInstalledPluginsFn> = vi.fn();
|
||||
export const updateNpmInstalledHookPacks: Mock<UpdateNpmInstalledHookPacksFn> = vi.fn();
|
||||
export const promptYesNo: AsyncUnknownMock = vi.fn();
|
||||
@@ -482,18 +494,6 @@ vi.mock("../plugins/uninstall.js", async (importOriginal) => {
|
||||
applyPluginUninstallDirectoryRemoval,
|
||||
...args,
|
||||
)) as (typeof import("../plugins/uninstall.js"))["applyPluginUninstallDirectoryRemoval"],
|
||||
uninstallPlugin: ((
|
||||
...args: Parameters<(typeof import("../plugins/uninstall.js"))["uninstallPlugin"]>
|
||||
) =>
|
||||
invokeMock<
|
||||
Parameters<(typeof import("../plugins/uninstall.js"))["uninstallPlugin"]>,
|
||||
ReturnType<(typeof import("../plugins/uninstall.js"))["uninstallPlugin"]>
|
||||
>(uninstallPlugin, ...args)) as (typeof import("../plugins/uninstall.js"))["uninstallPlugin"],
|
||||
resolveUninstallDirectoryTarget: ({
|
||||
installRecord,
|
||||
}: {
|
||||
installRecord?: { installPath?: string; sourcePath?: string };
|
||||
}) => installRecord?.installPath ?? installRecord?.sourcePath ?? null,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -732,7 +732,6 @@ export function resetPluginsCliTestState() {
|
||||
applyExclusiveSlotSelection.mockReset();
|
||||
planPluginUninstall.mockReset();
|
||||
applyPluginUninstallDirectoryRemoval.mockReset();
|
||||
uninstallPlugin.mockReset();
|
||||
updateNpmInstalledPlugins.mockReset();
|
||||
updateNpmInstalledHookPacks.mockReset();
|
||||
promptText.mockReset();
|
||||
@@ -860,12 +859,6 @@ export function resetPluginsCliTestState() {
|
||||
directoryRemoved: false,
|
||||
warnings: [],
|
||||
});
|
||||
uninstallPlugin.mockResolvedValue({
|
||||
ok: true,
|
||||
config: {} as OpenClawConfig,
|
||||
warnings: [],
|
||||
actions: createEmptyUninstallActions(),
|
||||
});
|
||||
updateNpmInstalledPlugins.mockResolvedValue({
|
||||
outcomes: [],
|
||||
changed: false,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Plugins CLI list tests cover plugin listing output and installed-state formatting.
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { createPluginRecord } from "../plugins/status.test-helpers.js";
|
||||
import { createPluginRecord } from "../plugins/status.test-fixtures.js";
|
||||
import {
|
||||
buildPluginDiagnosticsReport,
|
||||
buildPluginInspectReport,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Plugin list format tests cover installed plugin table and JSON formatting.
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { createPluginRecord } from "../plugins/status.test-helpers.js";
|
||||
import { createPluginRecord } from "../plugins/status.test-fixtures.js";
|
||||
import { formatPluginLine } from "./plugins-list-format.js";
|
||||
|
||||
describe("formatPluginLine", () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Plugin location bridge tests cover CLI plugin path bridging between install surfaces.
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { InstalledPluginStartupInfo } from "../plugins/installed-plugin-index-types.js";
|
||||
import type { InstalledPluginIndex } from "../plugins/installed-plugin-index.js";
|
||||
import type { InstalledPluginStartupInfo } from "../plugins/installed-plugin-index.js";
|
||||
import type { PluginManifestRegistry } from "../plugins/manifest-registry.js";
|
||||
|
||||
const readPersistedInstalledPluginIndexMock = vi.fn();
|
||||
|
||||
@@ -32,7 +32,7 @@ import {
|
||||
resetAgentEventsForTest,
|
||||
resetAgentRunContextForTest,
|
||||
} from "../infra/agent-events.js";
|
||||
import type { PluginProviderRegistration } from "../plugins/registry.js";
|
||||
import type { PluginProviderRegistration } from "../plugins/registry.test-fixtures.js";
|
||||
import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { AGENT_HARNESS_SESSION_KEY_RESERVED_MESSAGE } from "../sessions/agent-harness-session-key.js";
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { AuthProfileStore } from "../agents/auth-profiles.js";
|
||||
import type { ProviderAuthChoiceMetadata } from "../plugins/provider-auth-choices.js";
|
||||
import type { ProviderWizardOption } from "../plugins/provider-wizard.js";
|
||||
import {
|
||||
buildAuthChoiceGroups,
|
||||
buildAuthChoiceOptions,
|
||||
@@ -10,6 +9,10 @@ import {
|
||||
} from "./auth-choice-options.js";
|
||||
import { formatStaticAuthChoiceChoicesForCli } from "./auth-choice-options.static.js";
|
||||
|
||||
type ProviderWizardOption = ReturnType<
|
||||
(typeof import("../plugins/provider-wizard.js"))["resolveProviderWizardOptions"]
|
||||
>[number];
|
||||
|
||||
const resolveManifestProviderAuthChoices = vi.hoisted(() =>
|
||||
vi.fn<() => ProviderAuthChoiceMetadata[]>(() => []),
|
||||
);
|
||||
|
||||
@@ -3,7 +3,6 @@ import { expectDefined } from "@openclaw/normalization-core";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
applyAuthChoiceLoadedPluginProvider,
|
||||
applyAuthChoicePluginProvider,
|
||||
runProviderPluginAuthMethod,
|
||||
} from "../plugins/provider-auth-choice.js";
|
||||
import type { ProviderPlugin } from "../plugins/types.js";
|
||||
@@ -678,131 +677,4 @@ describe("applyAuthChoiceLoadedPluginProvider", () => {
|
||||
"openai/gpt-5.2": {},
|
||||
});
|
||||
});
|
||||
|
||||
it("returns an agent-scoped override for plugin auth choices when default model application is deferred", async () => {
|
||||
const provider = buildProvider();
|
||||
resolvePluginProviders.mockReturnValue([provider]);
|
||||
|
||||
const note = vi.fn(async () => {});
|
||||
const result = await applyAuthChoicePluginProvider(
|
||||
buildParams({
|
||||
authChoice: `provider-plugin:${LOCAL_PROVIDER_ID}:${LOCAL_AUTH_METHOD_ID}`,
|
||||
agentId: "worker",
|
||||
setDefaultModel: false,
|
||||
prompter: {
|
||||
note,
|
||||
} as unknown as ApplyAuthChoiceParams["prompter"],
|
||||
}),
|
||||
{
|
||||
authChoice: `provider-plugin:${LOCAL_PROVIDER_ID}:${LOCAL_AUTH_METHOD_ID}`,
|
||||
pluginId: LOCAL_PROVIDER_ID,
|
||||
providerId: LOCAL_PROVIDER_ID,
|
||||
methodId: LOCAL_AUTH_METHOD_ID,
|
||||
label: LOCAL_PROVIDER_LABEL,
|
||||
},
|
||||
);
|
||||
|
||||
expect(result?.agentModelOverride).toBe(LOCAL_DEFAULT_MODEL);
|
||||
expect(result?.config.plugins).toEqual({
|
||||
entries: {
|
||||
[LOCAL_PROVIDER_ID]: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(runProviderModelSelectedHook).not.toHaveBeenCalled();
|
||||
expect(note).toHaveBeenCalledWith(
|
||||
`Default model set to ${LOCAL_DEFAULT_MODEL} for agent "worker".`,
|
||||
"Model configured",
|
||||
);
|
||||
});
|
||||
|
||||
it("preserves the existing primary model for plugin auth choices that patch defaults", async () => {
|
||||
const provider = buildProviderWithDefaultModelPatch();
|
||||
resolvePluginProviders.mockReturnValue([provider]);
|
||||
const note = vi.fn(async () => {});
|
||||
|
||||
const result = await applyAuthChoicePluginProvider(
|
||||
buildParams({
|
||||
authChoice: `provider-plugin:${LOCAL_PROVIDER_ID}:${LOCAL_AUTH_METHOD_ID}`,
|
||||
config: {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: EXISTING_DEFAULT_MODEL },
|
||||
models: {
|
||||
[EXISTING_DEFAULT_MODEL]: { alias: "Bedrock" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
prompter: {
|
||||
note,
|
||||
} as unknown as ApplyAuthChoiceParams["prompter"],
|
||||
preserveExistingDefaultModel: true,
|
||||
}),
|
||||
{
|
||||
authChoice: `provider-plugin:${LOCAL_PROVIDER_ID}:${LOCAL_AUTH_METHOD_ID}`,
|
||||
pluginId: LOCAL_PROVIDER_ID,
|
||||
providerId: LOCAL_PROVIDER_ID,
|
||||
methodId: LOCAL_AUTH_METHOD_ID,
|
||||
label: LOCAL_PROVIDER_LABEL,
|
||||
},
|
||||
);
|
||||
|
||||
expect(result?.config.agents?.defaults?.model).toEqual({
|
||||
primary: EXISTING_DEFAULT_MODEL,
|
||||
});
|
||||
expect(result?.config.agents?.defaults?.models).toEqual({
|
||||
[EXISTING_DEFAULT_MODEL]: { alias: "Bedrock" },
|
||||
[LOCAL_DEFAULT_MODEL]: { alias: "Local default" },
|
||||
});
|
||||
expect(result?.config.plugins).toEqual({
|
||||
entries: {
|
||||
[LOCAL_PROVIDER_ID]: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(runProviderModelSelectedHook).not.toHaveBeenCalled();
|
||||
expect(note).toHaveBeenCalledWith(
|
||||
`Kept existing default model ${EXISTING_DEFAULT_MODEL}; ${LOCAL_DEFAULT_MODEL} is available.`,
|
||||
"Model configured",
|
||||
);
|
||||
});
|
||||
|
||||
it("stops early when the plugin is disabled in config", async () => {
|
||||
const note = vi.fn(async () => {});
|
||||
|
||||
const result = await applyAuthChoicePluginProvider(
|
||||
buildParams({
|
||||
config: {
|
||||
plugins: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
prompter: {
|
||||
note,
|
||||
} as unknown as ApplyAuthChoiceParams["prompter"],
|
||||
}),
|
||||
{
|
||||
authChoice: LOCAL_PROVIDER_ID,
|
||||
pluginId: LOCAL_PROVIDER_ID,
|
||||
providerId: LOCAL_PROVIDER_ID,
|
||||
label: LOCAL_PROVIDER_LABEL,
|
||||
},
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
config: {
|
||||
plugins: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(resolvePluginProviders).not.toHaveBeenCalled();
|
||||
expect(note).toHaveBeenCalledWith(
|
||||
"Local Provider plugin is disabled (plugins disabled).",
|
||||
LOCAL_PROVIDER_LABEL,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,7 +6,6 @@ import { resolveAgentDir } from "../agents/agent-scope.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { resolveAgentModelPrimaryValue } from "../config/model-input.js";
|
||||
import type { ModelProviderConfig } from "../config/types.models.js";
|
||||
import { testing as providerAuthChoiceTesting } from "../plugins/provider-auth-choice.js";
|
||||
import * as providerAuthChoices from "../plugins/provider-auth-choices.js";
|
||||
import type { ProviderAuthMethod, ProviderAuthResult, ProviderPlugin } from "../plugins/types.js";
|
||||
import type { WizardPrompter } from "../wizard/prompts.js";
|
||||
@@ -47,6 +46,13 @@ vi.mock("../plugins/provider-install-catalog.js", () => ({
|
||||
resolveProviderInstallCatalogEntry: vi.fn(() => undefined),
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/provider-auth-choice.runtime.js", () => ({
|
||||
resolvePluginProviders,
|
||||
resolvePluginSetupProvider: () => undefined,
|
||||
resolveProviderPluginChoice,
|
||||
runProviderModelSelectedHook,
|
||||
}));
|
||||
|
||||
vi.mock("./auth-choice.apply.api-providers.js", () => {
|
||||
const normalizeProviderIdLocal = (value: string) => value.trim().toLowerCase();
|
||||
const resolveChoiceByKind = (params: {
|
||||
@@ -673,18 +679,9 @@ describe("applyAuthChoice", () => {
|
||||
authTestRoot = (await setupAuthTestEnv("openclaw-auth-")).stateDir;
|
||||
defaultProviderPlugins = await createDefaultProviderPlugins();
|
||||
resolvePluginProviders.mockReturnValue(defaultProviderPlugins);
|
||||
providerAuthChoiceTesting.setDepsForTest({
|
||||
loadPluginProviderRuntime: async () => ({
|
||||
resolvePluginProviders,
|
||||
resolvePluginSetupProvider: () => undefined,
|
||||
resolveProviderPluginChoice,
|
||||
runProviderModelSelectedHook,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
providerAuthChoiceTesting.resetDepsForTest();
|
||||
if (authTestRoot) {
|
||||
await fs.rm(authTestRoot, { recursive: true, force: true });
|
||||
}
|
||||
@@ -1117,81 +1114,6 @@ describe("applyAuthChoice", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("enables the owning plugin for manifest provider auth choices", async () => {
|
||||
await setupTempState();
|
||||
const provider = createFixedChoiceProvider({
|
||||
providerId: "github-copilot",
|
||||
label: "GitHub Copilot",
|
||||
choiceId: "github-copilot-github",
|
||||
method: {
|
||||
id: "github",
|
||||
label: "GitHub Copilot",
|
||||
kind: "token",
|
||||
run: vi.fn(
|
||||
async (): Promise<ProviderAuthResult> => ({
|
||||
profiles: [
|
||||
{
|
||||
profileId: "github-copilot:github",
|
||||
credential: {
|
||||
type: "token",
|
||||
provider: "github-copilot",
|
||||
token: "gho_copilot_test",
|
||||
},
|
||||
},
|
||||
],
|
||||
defaultModel: "github-copilot/claude-opus-4.7",
|
||||
}),
|
||||
),
|
||||
},
|
||||
});
|
||||
const manifestSpy = vi
|
||||
.spyOn(providerAuthChoices, "resolveManifestProviderAuthChoice")
|
||||
.mockReturnValue({
|
||||
pluginId: "github-copilot",
|
||||
providerId: "github-copilot",
|
||||
methodId: "github",
|
||||
choiceId: "github-copilot-github",
|
||||
choiceLabel: "GitHub Copilot",
|
||||
});
|
||||
providerAuthChoiceTesting.setDepsForTest({
|
||||
loadPluginProviderRuntime: async () => ({
|
||||
resolvePluginProviders,
|
||||
resolvePluginSetupProvider: () => provider,
|
||||
resolveProviderPluginChoice,
|
||||
runProviderModelSelectedHook,
|
||||
}),
|
||||
});
|
||||
try {
|
||||
const result = await applyAuthChoice({
|
||||
authChoice: "github-copilot-github",
|
||||
config: { plugins: { entries: { "github-copilot": { enabled: false } } } },
|
||||
prompter: createPrompter({}),
|
||||
runtime: createExitThrowingRuntime(),
|
||||
setDefaultModel: true,
|
||||
preserveExistingDefaultModel: true,
|
||||
});
|
||||
|
||||
expect(result.config.plugins?.entries?.["github-copilot"]).toEqual({ enabled: true });
|
||||
expectAuthProfileConfig(result, "github-copilot:github", {
|
||||
provider: "github-copilot",
|
||||
mode: "token",
|
||||
});
|
||||
expect(resolveAgentModelPrimaryValue(result.config.agents?.defaults?.model)).toBe(
|
||||
"github-copilot/claude-opus-4.7",
|
||||
);
|
||||
} finally {
|
||||
manifestSpy.mockRestore();
|
||||
providerAuthChoiceTesting.setDepsForTest({
|
||||
loadPluginProviderRuntime: async () => ({
|
||||
resolvePluginProviders,
|
||||
resolvePluginSetupProvider: () => undefined,
|
||||
resolveProviderPluginChoice,
|
||||
runProviderModelSelectedHook,
|
||||
}),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it("uses explicit env for plugin auth resolution instead of host env", async () => {
|
||||
await setupTempState();
|
||||
process.env.OPENAI_API_KEY = "sk-openai-host"; // pragma: allowlist secret
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Config validation tests cover config snapshot validation and command error handling.
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { PluginCompatibilityNotice } from "../plugins/status.js";
|
||||
import { createCompatibilityNotice } from "../plugins/status.test-helpers.js";
|
||||
import { createCompatibilityNotice } from "../plugins/status.test-fixtures.js";
|
||||
import { requireValidConfigSnapshot } from "./config-validation.js";
|
||||
|
||||
const { readConfigFileSnapshot, buildPluginCompatibilitySnapshotNotices } = vi.hoisted(() => ({
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
createPluginLoadResult,
|
||||
createPluginRecord,
|
||||
createTypedHook,
|
||||
} from "../plugins/status.test-helpers.js";
|
||||
} from "../plugins/status.test-fixtures.js";
|
||||
import {
|
||||
collectWorkspaceStatusHealthFindings,
|
||||
noteWorkspaceStatus,
|
||||
|
||||
@@ -5,7 +5,7 @@ import path from "node:path";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ChannelAccountSnapshot } from "../channels/plugins/types.js";
|
||||
import type { ChannelPlugin } from "../channels/plugins/types.js";
|
||||
import { createPluginRecord } from "../plugins/status.test-helpers.js";
|
||||
import { createPluginRecord } from "../plugins/status.test-fixtures.js";
|
||||
import { MAX_TIMER_TIMEOUT_MS } from "../shared/number-coercion.js";
|
||||
import type { HealthSummary } from "./health.js";
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import type { Mock } from "vitest";
|
||||
import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import type { PluginCompatibilityNotice } from "../plugins/status.js";
|
||||
import { createCompatibilityNotice } from "../plugins/status.test-helpers.js";
|
||||
import { createCompatibilityNotice } from "../plugins/status.test-fixtures.js";
|
||||
import { captureEnv, deleteTestEnvValue, setTestEnvValue } from "../test-utils/env.js";
|
||||
|
||||
let envSnapshot: ReturnType<typeof captureEnv>;
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
// Verifies pruning-related config defaults and migrations.
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { setBundledPluginsDirOverrideForTest } from "../plugins/bundled-dir.js";
|
||||
import { resetBundledPluginPublicArtifactLoaderForTest } from "../plugins/public-surface-loader.js";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "./config.js";
|
||||
import { applyProviderConfigDefaultsForConfig } from "./provider-policy.js";
|
||||
|
||||
@@ -17,27 +14,6 @@ function applyAnthropicDefaultsForTest(config: OpenClawConfig) {
|
||||
}
|
||||
|
||||
describe("config pruning defaults", () => {
|
||||
beforeAll(() => {
|
||||
setBundledPluginsDirOverrideForTest(path.resolve(import.meta.dirname, "../../extensions"));
|
||||
// Provider public artifacts are process-stable. Keep their one-time load out of assertions.
|
||||
applyAnthropicDefaultsForTest({ agents: { defaults: {} } });
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
setBundledPluginsDirOverrideForTest(path.resolve(import.meta.dirname, "../../extensions"));
|
||||
resetBundledPluginPublicArtifactLoaderForTest();
|
||||
vi.stubEnv(
|
||||
"OPENCLAW_BUNDLED_PLUGINS_DIR",
|
||||
path.resolve(import.meta.dirname, "../../extensions"),
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
setBundledPluginsDirOverrideForTest(undefined);
|
||||
resetBundledPluginPublicArtifactLoaderForTest();
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
|
||||
it("does not enable contextPruning by default", () => {
|
||||
const cfg = applyAnthropicDefaultsForTest({ agents: { defaults: {} } });
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
// Covers best-effort config IO reads and warning behavior.
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { executeSqliteQueryTakeFirstSync, getNodeSqliteKysely } from "../infra/kysely-sync.js";
|
||||
import { setBundledPluginsDirOverrideForTest } from "../plugins/bundled-dir.js";
|
||||
import type { DB as OpenClawStateKyselyDatabase } from "../state/openclaw-state-db.generated.js";
|
||||
import {
|
||||
closeOpenClawStateDatabaseForTest,
|
||||
@@ -16,7 +14,6 @@ import {
|
||||
readConfigFileSnapshot,
|
||||
readSourceConfigBestEffort,
|
||||
} from "./config.js";
|
||||
import { applyProviderConfigDefaultsForConfig } from "./provider-policy.js";
|
||||
import { withTempHome, writeOpenClawConfig } from "./test-helpers.js";
|
||||
|
||||
type ConfigHealthDatabase = Pick<OpenClawStateKyselyDatabase, "config_health_entries">;
|
||||
@@ -34,20 +31,10 @@ function readConfigHealthRow(env: NodeJS.ProcessEnv, configPath: string) {
|
||||
}
|
||||
|
||||
describe("readBestEffortConfig", () => {
|
||||
beforeAll(() => {
|
||||
setBundledPluginsDirOverrideForTest(path.resolve(import.meta.dirname, "../../extensions"));
|
||||
// Materialized reads use the process-stable provider policy cache.
|
||||
applyProviderConfigDefaultsForConfig({ provider: "anthropic", config: {}, env: {} });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
closeOpenClawStateDatabaseForTest();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
setBundledPluginsDirOverrideForTest(undefined);
|
||||
});
|
||||
|
||||
it("can read snapshots without updating config observation state", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configPath = await writeOpenClawConfig(home, {
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
// Verifies plugin auto-enable prefer-over precedence rules.
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import type { PluginManifestRegistry } from "../plugins/manifest-registry.js";
|
||||
import { cleanupTrackedTempDirs } from "../plugins/test-helpers/fs-fixtures.js";
|
||||
|
||||
vi.mock("../plugins/bundled-dir.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../plugins/bundled-dir.js")>();
|
||||
return {
|
||||
...actual,
|
||||
resolveBundledPluginsDir: (env: NodeJS.ProcessEnv = process.env) =>
|
||||
env.OPENCLAW_BUNDLED_PLUGINS_DIR,
|
||||
};
|
||||
});
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
function makeTempDir(): string {
|
||||
const trustedRoot = path.resolve("dist-runtime", "extensions");
|
||||
fs.mkdirSync(trustedRoot, { recursive: true });
|
||||
const dir = fs.mkdtempSync(path.join(trustedRoot, ".openclaw-plugin-prefer-over-"));
|
||||
tempDirs.push(dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
function writeBundledChannelPackage(rootDir: string, channelId: string): void {
|
||||
const pluginDir = path.join(rootDir, channelId);
|
||||
fs.mkdirSync(pluginDir, { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(pluginDir, "package.json"),
|
||||
JSON.stringify({
|
||||
openclaw: {
|
||||
channel: {
|
||||
id: channelId,
|
||||
label: "Cache Drift",
|
||||
selectionLabel: "Cache Drift",
|
||||
docsPath: `/channels/${channelId}`,
|
||||
blurb: "Cache drift fixture",
|
||||
},
|
||||
},
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(pluginDir, "openclaw.plugin.json"),
|
||||
JSON.stringify({
|
||||
id: channelId,
|
||||
configSchema: { type: "object" },
|
||||
channels: [channelId],
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(pluginDir, "index.js"),
|
||||
"export default { register() {} };\n",
|
||||
"utf-8",
|
||||
);
|
||||
}
|
||||
|
||||
const EMPTY_MANIFEST_REGISTRY: PluginManifestRegistry = {
|
||||
plugins: [],
|
||||
diagnostics: [],
|
||||
};
|
||||
|
||||
async function setBundledPluginsDirFixture(dir: string | undefined): Promise<void> {
|
||||
const { setBundledPluginsDirOverrideForTest } = await import("../plugins/bundled-dir.js");
|
||||
setBundledPluginsDirOverrideForTest(dir);
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
await setBundledPluginsDirFixture(undefined);
|
||||
vi.unstubAllEnvs();
|
||||
vi.resetModules();
|
||||
cleanupTrackedTempDirs(tempDirs);
|
||||
});
|
||||
|
||||
describe("plugin auto-enable preferOver", () => {
|
||||
it("tolerates bundled channel id metadata drift during auto-enable", async () => {
|
||||
vi.resetModules();
|
||||
const rootDir = makeTempDir();
|
||||
const channelId = "cache-drift-channel";
|
||||
writeBundledChannelPackage(rootDir, channelId);
|
||||
|
||||
vi.stubEnv("OPENCLAW_BUNDLED_PLUGINS_DIR", rootDir);
|
||||
await setBundledPluginsDirFixture(rootDir);
|
||||
const { normalizeChatChannelId } = await import("../channels/ids.js");
|
||||
expect(normalizeChatChannelId(channelId)).toBe(channelId);
|
||||
|
||||
vi.stubEnv("OPENCLAW_BUNDLED_PLUGINS_DIR", path.join(rootDir, "missing"));
|
||||
await setBundledPluginsDirFixture(undefined);
|
||||
const { materializePluginAutoEnableCandidates } = await import("./plugin-auto-enable.js");
|
||||
|
||||
const result = materializePluginAutoEnableCandidates({
|
||||
config: {
|
||||
channels: {
|
||||
[channelId]: { token: "configured" },
|
||||
fallback: { token: "configured" },
|
||||
},
|
||||
},
|
||||
candidates: [
|
||||
{
|
||||
pluginId: channelId,
|
||||
kind: "channel-configured",
|
||||
channelId,
|
||||
},
|
||||
{
|
||||
pluginId: "fallback",
|
||||
kind: "channel-configured",
|
||||
channelId: "fallback",
|
||||
},
|
||||
],
|
||||
env: {
|
||||
OPENCLAW_STATE_DIR: path.join(rootDir, "state"),
|
||||
OPENCLAW_BUNDLED_PLUGINS_DIR: path.join(rootDir, "missing"),
|
||||
},
|
||||
manifestRegistry: EMPTY_MANIFEST_REGISTRY,
|
||||
});
|
||||
|
||||
expect(result.config.channels?.[channelId]?.enabled).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -3,9 +3,9 @@ import path from "node:path";
|
||||
import { clearCurrentPluginMetadataSnapshot } from "../plugins/current-plugin-metadata-snapshot.js";
|
||||
import { resolveInstalledPluginIndexPolicyHash } from "../plugins/installed-plugin-index-policy.js";
|
||||
import type { PluginManifestRegistry } from "../plugins/manifest-registry.js";
|
||||
import { clearPluginMetadataLifecycleCaches } from "../plugins/plugin-metadata-lifecycle.js";
|
||||
import type { PluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
|
||||
import type { PluginOrigin } from "../plugins/plugin-origin.types.js";
|
||||
import { clearPluginSetupRegistryCache } from "../plugins/setup-registry.js";
|
||||
import { cleanupTrackedTempDirs, makeTrackedTempDir } from "../plugins/test-helpers/fs-fixtures.js";
|
||||
import type { OpenClawConfig } from "./types.openclaw.js";
|
||||
|
||||
@@ -14,7 +14,7 @@ const tempDirs: string[] = [];
|
||||
/** Clears auto-enable plugin caches and temp dirs between tests. */
|
||||
export function resetPluginAutoEnableTestState(): void {
|
||||
clearCurrentPluginMetadataSnapshot();
|
||||
clearPluginSetupRegistryCache();
|
||||
clearPluginMetadataLifecycleCaches();
|
||||
cleanupTrackedTempDirs(tempDirs);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@ import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { withTempHome as withTempHomeBase } from "openclaw/plugin-sdk/test-env";
|
||||
import { resetPluginLoaderTestStateForTest } from "../plugins/loader.test-fixtures.js";
|
||||
import { clearPluginSetupRegistryCache } from "../plugins/setup-registry.js";
|
||||
import { clearPluginMetadataLifecycleCaches } from "../plugins/plugin-metadata-lifecycle.js";
|
||||
import { resetConfigRuntimeState, type OpenClawConfig } from "./config.js";
|
||||
|
||||
function resetConfigTestRuntimeState(): void {
|
||||
resetConfigRuntimeState();
|
||||
resetPluginLoaderTestStateForTest();
|
||||
clearPluginSetupRegistryCache();
|
||||
clearPluginMetadataLifecycleCaches();
|
||||
}
|
||||
|
||||
export async function withTempHome<T>(fn: (home: string) => Promise<T>): Promise<T> {
|
||||
|
||||
@@ -3,7 +3,10 @@ import type { AgentMessage } from "openclaw/plugin-sdk/agent-core";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { MemoryCitationsMode } from "../config/types.memory.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { clearMemoryPluginState, registerMemoryPromptSection } from "../plugins/memory-state.js";
|
||||
import {
|
||||
clearMemoryPluginState,
|
||||
registerMemoryPromptSection,
|
||||
} from "../plugins/memory-state.test-fixtures.js";
|
||||
// ---------------------------------------------------------------------------
|
||||
// We dynamically import the registry so we can get a fresh module per test
|
||||
// group when needed. For most groups we use the shared singleton directly.
|
||||
|
||||
@@ -6,7 +6,7 @@ import { runEmbeddedAgent } from "../agents/embedded-agent.js";
|
||||
import { loadModelCatalog } from "../agents/model-catalog.js";
|
||||
import { BASE_THINKING_LEVELS } from "../auto-reply/thinking.shared.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { PluginProviderRegistration } from "../plugins/registry.js";
|
||||
import type { PluginProviderRegistration } from "../plugins/registry.test-fixtures.js";
|
||||
import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
import { createTestRegistry } from "../test-utils/channel-plugins.js";
|
||||
import {
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
getRuntimeConfig,
|
||||
} from "../config/config.js";
|
||||
import { isTruthyEnvValue } from "../infra/env.js";
|
||||
import { clearPluginLoaderCache } from "../plugins/loader.js";
|
||||
import { clearPluginLoaderCache } from "../plugins/loader.test-fixtures.js";
|
||||
import {
|
||||
pinActivePluginChannelRegistry,
|
||||
releasePinnedPluginChannelRegistry,
|
||||
|
||||
@@ -21,7 +21,7 @@ import { loadSessionStore } from "../config/sessions/store.js";
|
||||
import type { SessionEntry } from "../config/sessions/types.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { isTruthyEnvValue } from "../infra/env.js";
|
||||
import { clearPluginLoaderCache } from "../plugins/loader.js";
|
||||
import { clearPluginLoaderCache } from "../plugins/loader.test-fixtures.js";
|
||||
import { resetPluginRuntimeStateForTest } from "../plugins/runtime.js";
|
||||
import { setTestEnvValue } from "../test-utils/env.js";
|
||||
import { sleep } from "../utils.js";
|
||||
|
||||
@@ -13,7 +13,7 @@ import { isTruthyEnvValue } from "../infra/env.js";
|
||||
import { getSessionBindingService } from "../infra/outbound/session-binding-service.js";
|
||||
import { findBundledPluginMetadataById } from "../plugins/bundled-plugin-metadata.js";
|
||||
import { pluginCommands } from "../plugins/command-registry-state.js";
|
||||
import { clearPluginLoaderCache } from "../plugins/loader.js";
|
||||
import { clearPluginLoaderCache } from "../plugins/loader.test-fixtures.js";
|
||||
import {
|
||||
pinActivePluginChannelRegistry,
|
||||
releasePinnedPluginChannelRegistry,
|
||||
|
||||
@@ -62,7 +62,6 @@ import { isTruthyEnvValue } from "../infra/env.js";
|
||||
import type { ModelRegistry } from "../llm/model-registry.js";
|
||||
import { normalizeGoogleModelId } from "../plugin-sdk/google-model-id.js";
|
||||
import { resolveProviderThinkingProfile } from "../plugins/provider-runtime.js";
|
||||
import type { ProviderThinkingModelCompat } from "../plugins/provider-thinking.types.js";
|
||||
import { DEFAULT_AGENT_ID } from "../routing/session-key.js";
|
||||
import { stripAssistantInternalScaffolding } from "../shared/text/assistant-visible-text.js";
|
||||
import { findFinalTagMatches, stripFinalTags } from "../shared/text/final-tags.js";
|
||||
@@ -70,6 +69,11 @@ import { deleteTestEnvValue, setTestEnvValue } from "../test-utils/env.js";
|
||||
import { getFreePort, isPortFree } from "../test-utils/ports.js";
|
||||
import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js";
|
||||
import { GatewayClient } from "./client.js";
|
||||
|
||||
type ProviderThinkingModelCompat = {
|
||||
thinkingFormat?: string;
|
||||
supportedReasoningEfforts?: readonly string[] | null;
|
||||
};
|
||||
import {
|
||||
hasExpectedSingleNonce,
|
||||
hasExpectedToolNonce,
|
||||
|
||||
@@ -17,7 +17,7 @@ import { clearSessionStoreCacheForTest } from "../config/sessions/store.js";
|
||||
import type { GatewayAuthConfig, GatewayTailscaleConfig } from "../config/types.gateway.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { resetAgentRunContextForTest } from "../infra/agent-events.js";
|
||||
import { clearGatewaySubagentRuntime } from "../plugins/runtime/index.js";
|
||||
import { clearGatewaySubagentRuntime } from "../plugins/runtime/gateway-bindings.test-fixtures.js";
|
||||
import { captureEnv, deleteTestEnvValue, setTestEnvValue } from "../test-utils/env.js";
|
||||
import { startGatewayServer } from "./server.js";
|
||||
import {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { clearConfigCache, clearRuntimeConfigSnapshot } from "../config/config.j
|
||||
import { clearSessionStoreCacheForTest } from "../config/sessions/store.js";
|
||||
import { resetAgentRunContextForTest } from "../infra/agent-events.js";
|
||||
import { PROXY_ENV_KEYS } from "../infra/net/proxy-env.js";
|
||||
import { clearGatewaySubagentRuntime } from "../plugins/runtime/index.js";
|
||||
import { clearGatewaySubagentRuntime } from "../plugins/runtime/gateway-bindings.test-fixtures.js";
|
||||
import { captureEnv, deleteTestEnvValue, setTestEnvValue } from "../test-utils/env.js";
|
||||
import { startGatewayServer } from "./server.js";
|
||||
import { getFreeGatewayPort } from "./test-helpers.e2e.js";
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createBundledBrowserPluginFixture } from "../../test/helpers/browser-bundled-plugin-fixture.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { clearPluginLoaderCache } from "../plugins/loader.js";
|
||||
import { clearPluginLoaderCache } from "../plugins/loader.test-fixtures.js";
|
||||
import { resetPluginRuntimeStateForTest } from "../plugins/runtime.js";
|
||||
import { loadGatewayStartupPlugins } from "./server-plugin-bootstrap.js";
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import type { PluginRuntimeGatewayRequestScope } from "../plugins/runtime/gateway-request-scope.js";
|
||||
import type { PluginRuntimeGatewayRequestScope } from "../plugins/runtime/gateway-request-scope.test-fixtures.js";
|
||||
import type { GatewayRequestContext, GatewayRequestOptions } from "./server-methods/types.js";
|
||||
|
||||
type HandleGatewayRequestOptions = GatewayRequestOptions & {
|
||||
|
||||
@@ -5,7 +5,8 @@ import { createPluginRecord } from "../plugins/loader-records.js";
|
||||
import type { PluginLookUpTable } from "../plugins/plugin-lookup-table.js";
|
||||
import { createEmptyPluginRegistry } from "../plugins/registry-empty.js";
|
||||
import type { PluginRegistry } from "../plugins/registry.js";
|
||||
import type { PluginRuntimeGatewayRequestScope } from "../plugins/runtime/gateway-request-scope.js";
|
||||
import { clearGatewaySubagentRuntime } from "../plugins/runtime/gateway-bindings.test-fixtures.js";
|
||||
import type { PluginRuntimeGatewayRequestScope } from "../plugins/runtime/gateway-request-scope.test-fixtures.js";
|
||||
import type { PluginRuntime } from "../plugins/runtime/types.js";
|
||||
import type { PluginDiagnostic } from "../plugins/types.js";
|
||||
import type { GatewayRequestContext, GatewayRequestOptions } from "./server-methods/types.js";
|
||||
@@ -381,7 +382,7 @@ beforeEach(() => {
|
||||
pluginRuntimeLoaderLogger.error.mockClear();
|
||||
pluginRuntimeLoaderLogger.debug.mockClear();
|
||||
handleGatewayRequest.mockReset();
|
||||
runtimeModule.clearGatewaySubagentRuntime();
|
||||
clearGatewaySubagentRuntime();
|
||||
handleGatewayRequest.mockImplementation(async (opts: HandleGatewayRequestOptions) => {
|
||||
switch (opts.req.method) {
|
||||
case "agent":
|
||||
@@ -404,7 +405,7 @@ beforeEach(() => {
|
||||
|
||||
afterEach(() => {
|
||||
serverPluginsModule.clearFallbackGatewayContext();
|
||||
runtimeModule.clearGatewaySubagentRuntime();
|
||||
clearGatewaySubagentRuntime();
|
||||
runtimeRegistryModule.resetPluginRuntimeStateForTest();
|
||||
});
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
releasePinnedPluginSessionExtensionRegistry,
|
||||
setActivePluginRegistry,
|
||||
} from "../plugins/runtime.js";
|
||||
import { createPluginRecord } from "../plugins/status.test-helpers.js";
|
||||
import { createPluginRecord } from "../plugins/status.test-fixtures.js";
|
||||
import { buildGatewaySessionRow } from "./session-utils.js";
|
||||
import { embeddedRunMock, rpcReq, testState, writeSessionStore } from "./test-helpers.js";
|
||||
import {
|
||||
|
||||
@@ -36,7 +36,7 @@ import { __testing as restartTesting } from "../infra/restart.js";
|
||||
import { drainSystemEvents, peekSystemEvents } from "../infra/system-events.js";
|
||||
import { rawDataToString } from "../infra/ws.js";
|
||||
import { resetLogger, setLoggerOverride } from "../logging.js";
|
||||
import { clearGatewaySubagentRuntime } from "../plugins/runtime/gateway-bindings.js";
|
||||
import { clearGatewaySubagentRuntime } from "../plugins/runtime/gateway-bindings.test-fixtures.js";
|
||||
import { resetGatewayWorkAdmission } from "../process/gateway-work-admission.js";
|
||||
import {
|
||||
DEFAULT_AGENT_ID,
|
||||
|
||||
@@ -16,7 +16,7 @@ import type { OpenClawConfig } from "../../config/config.js";
|
||||
import type { SessionTranscriptAppendResult } from "../../config/sessions/transcript.js";
|
||||
import * as mediaCapabilityModule from "../../media/read-capability.js";
|
||||
import { createHookRunner } from "../../plugins/hooks.js";
|
||||
import { addTestHook } from "../../plugins/hooks.test-helpers.js";
|
||||
import { addTestHook } from "../../plugins/hooks.test-fixtures.js";
|
||||
import { createEmptyPluginRegistry } from "../../plugins/registry.js";
|
||||
import {
|
||||
pinActivePluginChannelRegistry,
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
initializeGlobalHookRunner,
|
||||
resetGlobalHookRunner,
|
||||
} from "../plugins/hook-runner-global.js";
|
||||
import { createMockPluginRegistry } from "../plugins/hooks.test-helpers.js";
|
||||
import { createMockPluginRegistry } from "../plugins/hooks.test-fixtures.js";
|
||||
import { PluginApprovalResolutions } from "../plugins/types.js";
|
||||
import { createPluginToolsMcpHandlers } from "./plugin-tools-handlers.js";
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
withBundledPluginEnablementCompat,
|
||||
withBundledPluginVitestCompat,
|
||||
} from "../plugins/bundled-compat.js";
|
||||
import { testing as loaderTesting } from "../plugins/loader.js";
|
||||
import { resolvePluginRegistryLoadCacheKey } from "../plugins/loader.js";
|
||||
import { loadPluginManifestRegistry } from "../plugins/manifest-registry.js";
|
||||
import { createEmptyPluginRegistry } from "../plugins/registry.js";
|
||||
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
@@ -92,7 +92,7 @@ function setCompatibleActiveMediaUnderstandingRegistry(
|
||||
pluginIds,
|
||||
env: process.env,
|
||||
});
|
||||
const { cacheKey } = loaderTesting.resolvePluginLoadCacheContext({
|
||||
const cacheKey = resolvePluginRegistryLoadCacheKey({
|
||||
config: compatibleConfig,
|
||||
env: process.env,
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
initializeGlobalHookRunner,
|
||||
resetGlobalHookRunner,
|
||||
} from "../plugins/hook-runner-global.js";
|
||||
import { createMockPluginRegistry } from "../plugins/hooks.test-helpers.js";
|
||||
import { createMockPluginRegistry } from "../plugins/hooks.test-fixtures.js";
|
||||
import { issuePairingChallenge } from "./pairing-challenge.js";
|
||||
|
||||
describe("issuePairingChallenge", () => {
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
initializeGlobalHookRunner,
|
||||
resetGlobalHookRunner,
|
||||
} from "../plugins/hook-runner-global.js";
|
||||
import { createMockPluginRegistry } from "../plugins/hooks.test-helpers.js";
|
||||
import { createMockPluginRegistry } from "../plugins/hooks.test-fixtures.js";
|
||||
import type { PluginRuntime } from "../plugins/runtime/types.js";
|
||||
import {
|
||||
createChannelPairingChallengeIssuer,
|
||||
|
||||
@@ -4,7 +4,6 @@ import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { clearRuntimeConfigSnapshot, setRuntimeConfigSnapshot } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { setBundledPluginsDirOverrideForTest } from "../plugins/bundled-dir.js";
|
||||
import { createPluginActivationSource, normalizePluginsConfig } from "../plugins/config-state.js";
|
||||
import {
|
||||
clearCurrentPluginMetadataSnapshot,
|
||||
@@ -72,7 +71,6 @@ function createBundledPluginDir(prefix: string, marker: string): string {
|
||||
|
||||
function useBundledPluginDirOverrideForTest(dir: string): void {
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = dir;
|
||||
setBundledPluginsDirOverrideForTest(dir);
|
||||
}
|
||||
|
||||
function createThrowingPluginDir(prefix: string): string {
|
||||
@@ -102,7 +100,6 @@ afterEach(() => {
|
||||
clearRuntimeConfigSnapshot();
|
||||
clearCurrentPluginMetadataSnapshot();
|
||||
resetFacadeRuntimeStateForTest();
|
||||
setBundledPluginsDirOverrideForTest(undefined);
|
||||
vi.doUnmock("../plugins/manifest-registry.js");
|
||||
if (originalBundledPluginsDir === undefined) {
|
||||
delete process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
clearMemoryPluginState,
|
||||
registerMemoryCapability,
|
||||
registerMemoryPromptSection,
|
||||
} from "../plugins/memory-state.js";
|
||||
} from "../plugins/memory-state.test-fixtures.js";
|
||||
import * as memoryCoreAlias from "./memory-core.js";
|
||||
import {
|
||||
buildActiveMemoryPromptSection,
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
import { getCurrentPluginMetadataSnapshot } from "./current-plugin-metadata-snapshot.js";
|
||||
import type { PluginDiscoveryResult } from "./discovery.js";
|
||||
|
||||
export type PluginActivationCompatConfig = {
|
||||
type PluginActivationCompatConfig = {
|
||||
enablementPluginIds?: readonly string[];
|
||||
vitestPluginIds?: readonly string[];
|
||||
};
|
||||
@@ -24,7 +24,7 @@ export type PluginActivationBundledCompatMode = {
|
||||
vitest?: boolean;
|
||||
};
|
||||
|
||||
export type PluginActivationInputs = {
|
||||
type PluginActivationInputs = {
|
||||
rawConfig?: OpenClawConfig;
|
||||
config?: OpenClawConfig;
|
||||
normalized: NormalizedPluginsConfig;
|
||||
@@ -33,11 +33,11 @@ export type PluginActivationInputs = {
|
||||
autoEnabledReasons: Record<string, string[]>;
|
||||
};
|
||||
|
||||
export type BundledPluginCompatibleActivationInputs = PluginActivationInputs & {
|
||||
type BundledPluginCompatibleActivationInputs = PluginActivationInputs & {
|
||||
compatPluginIds: string[];
|
||||
};
|
||||
|
||||
export type BundledPluginCompatibleLoadValues = Pick<
|
||||
type BundledPluginCompatibleLoadValues = Pick<
|
||||
BundledPluginCompatibleActivationInputs,
|
||||
"rawConfig" | "config" | "activationSourceConfig" | "autoEnabledReasons" | "compatPluginIds"
|
||||
>;
|
||||
|
||||
@@ -17,7 +17,7 @@ import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry-c
|
||||
import { createPluginIdScopeSet, normalizePluginIdScope } from "./plugin-scope.js";
|
||||
|
||||
/** Runtime surface that can request a lazily activated plugin owner. */
|
||||
export type PluginActivationPlannerTrigger =
|
||||
type PluginActivationPlannerTrigger =
|
||||
| { kind: "command"; command: string }
|
||||
| { kind: "provider"; provider: string }
|
||||
| { kind: "agentHarness"; runtime: string }
|
||||
@@ -25,7 +25,7 @@ export type PluginActivationPlannerTrigger =
|
||||
| { kind: "route"; route: string }
|
||||
| { kind: "capability"; capability: PluginManifestActivationCapability };
|
||||
|
||||
export type PluginActivationPlannerHintReason =
|
||||
type PluginActivationPlannerHintReason =
|
||||
| "activation-agent-harness-hint"
|
||||
| "activation-capability-hint"
|
||||
| "activation-channel-hint"
|
||||
@@ -33,7 +33,7 @@ export type PluginActivationPlannerHintReason =
|
||||
| "activation-provider-hint"
|
||||
| "activation-route-hint";
|
||||
|
||||
export type PluginActivationPlannerManifestReason =
|
||||
type PluginActivationPlannerManifestReason =
|
||||
| "manifest-channel-owner"
|
||||
| "manifest-command-alias"
|
||||
| "manifest-hook-owner"
|
||||
@@ -41,11 +41,11 @@ export type PluginActivationPlannerManifestReason =
|
||||
| "manifest-setup-provider-owner"
|
||||
| "manifest-tool-contract";
|
||||
|
||||
export type PluginActivationPlannerReason =
|
||||
type PluginActivationPlannerReason =
|
||||
| PluginActivationPlannerHintReason
|
||||
| PluginActivationPlannerManifestReason;
|
||||
|
||||
export type PluginActivationPlanEntry = {
|
||||
type PluginActivationPlanEntry = {
|
||||
pluginId: string;
|
||||
origin: PluginOrigin;
|
||||
reasons: readonly PluginActivationPlannerReason[];
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
getLoadedRuntimePluginRegistry,
|
||||
listLoadedRuntimePluginIdsAcrossSurfaces,
|
||||
} from "./active-runtime-registry.js";
|
||||
import { testing, clearPluginLoaderCache } from "./loader.js";
|
||||
import { clearPluginLoaderCache } from "./loader.test-fixtures.js";
|
||||
import { createEmptyPluginRegistry } from "./registry-empty.js";
|
||||
import type { PluginRegistry } from "./registry-types.js";
|
||||
import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "./runtime.js";
|
||||
@@ -149,38 +149,4 @@ describe("getLoadedRuntimePluginRegistry", () => {
|
||||
}),
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it("validates full loader cache compatibility when load options are provided", () => {
|
||||
const registry = createRegistryWithPlugin("demo");
|
||||
const loadOptions = {
|
||||
config: {
|
||||
plugins: {
|
||||
allow: ["demo"],
|
||||
},
|
||||
},
|
||||
onlyPluginIds: ["demo"],
|
||||
workspaceDir: "/tmp/ws",
|
||||
};
|
||||
const { cacheKey } = testing.resolvePluginLoadCacheContext(loadOptions);
|
||||
setActivePluginRegistry(registry, cacheKey, "default", "/tmp/ws");
|
||||
|
||||
expect(
|
||||
getLoadedRuntimePluginRegistry({
|
||||
loadOptions,
|
||||
}),
|
||||
).toBe(registry);
|
||||
|
||||
expect(
|
||||
getLoadedRuntimePluginRegistry({
|
||||
loadOptions: {
|
||||
...loadOptions,
|
||||
config: {
|
||||
plugins: {
|
||||
allow: ["other"],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -205,8 +205,3 @@ export async function loadAgentToolResultMiddlewaresForRuntime(params: {
|
||||
return listAgentToolResultMiddlewares(params.runtime);
|
||||
}
|
||||
}
|
||||
|
||||
export const testing = {
|
||||
listMiddlewareOwnerPluginIds,
|
||||
};
|
||||
export { testing as __testing };
|
||||
|
||||
@@ -54,11 +54,6 @@ export function normalizeAgentToolResultMiddlewareRuntimes(
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
/** @deprecated Use normalizeAgentToolResultMiddlewareRuntimes. */
|
||||
export const normalizeAgentToolResultMiddlewareHarnesses =
|
||||
normalizeAgentToolResultMiddlewareRuntimes;
|
||||
|
||||
export function normalizeAgentToolResultMiddlewareRuntimeIds(
|
||||
runtimes: readonly string[] | undefined,
|
||||
): AgentToolResultMiddlewareRuntime[] {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { attachPluginApiFacades, type OpenClawPluginApiWithoutFacades } from "./
|
||||
import type { PluginRuntime } from "./runtime/types.js";
|
||||
import type { OpenClawPluginApi, PluginLogger } from "./types.js";
|
||||
|
||||
export type BuildPluginApiParams = {
|
||||
type BuildPluginApiParams = {
|
||||
id: string;
|
||||
name: string;
|
||||
version?: string;
|
||||
|
||||
@@ -9,10 +9,10 @@ type FunctionPropertyNames<T> = Extract<
|
||||
>;
|
||||
|
||||
/** Names of plugin API methods exposed on the OpenClaw plugin API. */
|
||||
export type PluginApiMethodName = FunctionPropertyNames<OpenClawPluginApi>;
|
||||
type PluginApiMethodName = FunctionPropertyNames<OpenClawPluginApi>;
|
||||
|
||||
/** Lifecycle policy for whether a plugin API method can be called after registration. */
|
||||
export type PluginApiLifecyclePolicy = {
|
||||
type PluginApiLifecyclePolicy = {
|
||||
phase: "registration" | "runtime";
|
||||
lateCallable: boolean;
|
||||
};
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
} from "./config-state.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry-contributions.js";
|
||||
|
||||
export type ClaudeBundleCommandSpec = {
|
||||
type ClaudeBundleCommandSpec = {
|
||||
pluginId: string;
|
||||
rawName: string;
|
||||
description: string;
|
||||
|
||||
@@ -12,7 +12,7 @@ type ReadBundleJsonResult =
|
||||
| { ok: true; raw: Record<string, unknown> }
|
||||
| { ok: false; error: string };
|
||||
|
||||
export type BundleServerRuntimeSupport = {
|
||||
type BundleServerRuntimeSupport = {
|
||||
hasSupportedServer: boolean;
|
||||
supportedServerNames: string[];
|
||||
unsupportedServerNames: string[];
|
||||
|
||||
@@ -22,12 +22,12 @@ import type { PluginBundleFormat } from "./manifest-types.js";
|
||||
export type BundleLspServerConfig = Record<string, unknown>;
|
||||
|
||||
/** Merged LSP config contributed by enabled plugin bundles. */
|
||||
export type BundleLspConfig = {
|
||||
type BundleLspConfig = {
|
||||
lspServers: Record<string, BundleLspServerConfig>;
|
||||
};
|
||||
|
||||
/** Runtime support summary for bundle-declared LSP servers. */
|
||||
export type BundleLspRuntimeSupport = {
|
||||
type BundleLspRuntimeSupport = {
|
||||
hasStdioServer: boolean;
|
||||
supportedServerNames: string[];
|
||||
unsupportedServerNames: string[];
|
||||
|
||||
@@ -9,13 +9,17 @@ import {
|
||||
detectBundleManifestFormat,
|
||||
loadBundleManifest,
|
||||
} from "./bundle-manifest.js";
|
||||
import type { BundlePluginManifest } from "./bundle-manifest.js";
|
||||
import {
|
||||
cleanupTrackedTempDirs,
|
||||
makeTrackedTempDir,
|
||||
mkdirSafeDir,
|
||||
} from "./test-helpers/fs-fixtures.js";
|
||||
|
||||
type BundlePluginManifest = Extract<
|
||||
ReturnType<typeof loadBundleManifest>,
|
||||
{ ok: true }
|
||||
>["manifest"];
|
||||
|
||||
type ReadonlyBundleManifestExpectation = Omit<
|
||||
BundlePluginManifest,
|
||||
"capabilities" | "hooks" | "settingsFiles" | "skills"
|
||||
|
||||
@@ -24,7 +24,7 @@ export const CLAUDE_BUNDLE_MANIFEST_RELATIVE_PATH = ".claude-plugin/plugin.json"
|
||||
export const CURSOR_BUNDLE_MANIFEST_RELATIVE_PATH = ".cursor-plugin/plugin.json";
|
||||
|
||||
/** Normalized bundle manifest shape consumed by plugin discovery. */
|
||||
export type BundlePluginManifest = {
|
||||
type BundlePluginManifest = {
|
||||
id: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
@@ -38,7 +38,7 @@ export type BundlePluginManifest = {
|
||||
capabilities: string[];
|
||||
};
|
||||
|
||||
export type BundleManifestLoadResult =
|
||||
type BundleManifestLoadResult =
|
||||
| { ok: true; manifest: BundlePluginManifest; manifestPath: string }
|
||||
| { ok: false; error: string; manifestPath: string };
|
||||
|
||||
|
||||
@@ -32,11 +32,11 @@ export type BundleMcpDiagnostic = {
|
||||
message: string;
|
||||
};
|
||||
|
||||
export type EnabledBundleMcpConfigResult = {
|
||||
type EnabledBundleMcpConfigResult = {
|
||||
config: BundleMcpConfig;
|
||||
diagnostics: BundleMcpDiagnostic[];
|
||||
};
|
||||
export type BundleMcpRuntimeSupport = {
|
||||
type BundleMcpRuntimeSupport = {
|
||||
hasSupportedStdioServer: boolean;
|
||||
supportedServerNames: string[];
|
||||
unsupportedServerNames: string[];
|
||||
|
||||
@@ -1,21 +1,10 @@
|
||||
// Verifies bundled capability metadata emitted by plugins.
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { expectDefined } from "@openclaw/normalization-core";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { expectNoReaddirSyncDuring } from "../test-utils/fs-scan-assertions.js";
|
||||
import { listGitTrackedFiles, toRepoRelativePath } from "../test-utils/repo-files.js";
|
||||
import { normalizeBundledPluginStringList } from "./bundled-plugin-scan.js";
|
||||
import {
|
||||
BUNDLED_AUTO_ENABLE_PROVIDER_PLUGIN_IDS,
|
||||
BUNDLED_LEGACY_PLUGIN_ID_ALIASES,
|
||||
BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS,
|
||||
buildBundledPluginContractSnapshot,
|
||||
hasBundledPluginContractSnapshotCapabilities,
|
||||
} from "./contracts/inventory/bundled-capability-metadata.js";
|
||||
import { pluginTestRepoRoot as repoRoot } from "./generated-plugin-test-helpers.js";
|
||||
import type { OpenClawPackageManifest } from "./manifest.js";
|
||||
import type { PluginManifest } from "./manifest.js";
|
||||
|
||||
function listGitExtensionPackagePaths(extensionsDir: string): string[] | null {
|
||||
const relativeDir = toRepoRelativePath(repoRoot, extensionsDir);
|
||||
@@ -45,24 +34,6 @@ function listExtensionPackagePaths(extensionsDir: string): string[] {
|
||||
.filter((packagePath) => fs.existsSync(packagePath));
|
||||
}
|
||||
|
||||
function readManifestRecords(): PluginManifest[] {
|
||||
const extensionsDir = path.join(repoRoot, "extensions");
|
||||
return listExtensionPackagePaths(extensionsDir)
|
||||
.filter((packagePath) => {
|
||||
const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf-8")) as {
|
||||
openclaw?: OpenClawPackageManifest;
|
||||
};
|
||||
return normalizeBundledPluginStringList(packageJson.openclaw?.extensions).length > 0;
|
||||
})
|
||||
.map(
|
||||
(packagePath) =>
|
||||
JSON.parse(
|
||||
fs.readFileSync(path.join(path.dirname(packagePath), "openclaw.plugin.json"), "utf-8"),
|
||||
) as PluginManifest,
|
||||
)
|
||||
.toSorted((left, right) => left.id.localeCompare(right.id));
|
||||
}
|
||||
|
||||
describe("bundled capability metadata", () => {
|
||||
it("lists bundled extension packages from git without scanning extension dirs", () => {
|
||||
const extensionsDir = path.join(repoRoot, "extensions");
|
||||
@@ -73,69 +44,4 @@ describe("bundled capability metadata", () => {
|
||||
expect(packagePaths.every((file) => file.endsWith("package.json"))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps contract snapshots aligned with bundled plugin manifests", () => {
|
||||
const expected = readManifestRecords()
|
||||
.map(buildBundledPluginContractSnapshot)
|
||||
.filter(hasBundledPluginContractSnapshotCapabilities)
|
||||
.toSorted((left, right) => left.pluginId.localeCompare(right.pluginId));
|
||||
|
||||
expect(BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS).toEqual(expected);
|
||||
expect(
|
||||
BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS.find((entry) => entry.pluginId === "migrate-hermes"),
|
||||
).toEqual({
|
||||
pluginId: "migrate-hermes",
|
||||
cliBackendIds: [],
|
||||
providerIds: [],
|
||||
providerEnvVars: {},
|
||||
workerProviderIds: [],
|
||||
embeddingProviderIds: [],
|
||||
speechProviderIds: [],
|
||||
realtimeTranscriptionProviderIds: [],
|
||||
realtimeVoiceProviderIds: [],
|
||||
mediaUnderstandingProviderIds: [],
|
||||
transcriptSourceProviderIds: [],
|
||||
documentExtractorIds: [],
|
||||
imageGenerationProviderIds: [],
|
||||
videoGenerationProviderIds: [],
|
||||
musicGenerationProviderIds: [],
|
||||
webContentExtractorIds: [],
|
||||
webFetchProviderIds: [],
|
||||
webSearchProviderIds: [],
|
||||
migrationProviderIds: ["hermes"],
|
||||
toolNames: [],
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps lightweight alias maps aligned with bundled plugin manifests", () => {
|
||||
const manifests = readManifestRecords();
|
||||
const expectedLegacyAliases = Object.fromEntries(
|
||||
manifests
|
||||
.flatMap((manifest) =>
|
||||
(manifest.legacyPluginIds ?? []).map((legacyPluginId) => [legacyPluginId, manifest.id]),
|
||||
)
|
||||
.toSorted(([left], [right]) =>
|
||||
expectDefined(left, "left test invariant").localeCompare(
|
||||
expectDefined(right, "right test invariant"),
|
||||
),
|
||||
),
|
||||
);
|
||||
const expectedAutoEnableProviderPluginIds = Object.fromEntries(
|
||||
manifests
|
||||
.flatMap((manifest) =>
|
||||
(manifest.autoEnableWhenConfiguredProviders ?? []).map((providerId) => [
|
||||
providerId,
|
||||
manifest.id,
|
||||
]),
|
||||
)
|
||||
.toSorted(([left], [right]) =>
|
||||
expectDefined(left, "left test invariant").localeCompare(
|
||||
expectDefined(right, "right test invariant"),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(BUNDLED_LEGACY_PLUGIN_ID_ALIASES).toEqual(expectedLegacyAliases);
|
||||
expect(BUNDLED_AUTO_ENABLE_PROVIDER_PLUGIN_IDS).toEqual(expectedAutoEnableProviderPluginIds);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
// Verifies bundled capability runtime registration from plugin metadata.
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildVitestCapabilityShimAliasMap } from "./bundled-capability-runtime.js";
|
||||
|
||||
describe("buildVitestCapabilityShimAliasMap", () => {
|
||||
it("keeps scoped and unscoped capability shim aliases aligned", () => {
|
||||
const aliasMap = buildVitestCapabilityShimAliasMap();
|
||||
|
||||
expect(aliasMap["openclaw/plugin-sdk/config-runtime"]).toBe(
|
||||
aliasMap["@openclaw/plugin-sdk/config-runtime"],
|
||||
);
|
||||
expect(aliasMap["openclaw/plugin-sdk/media-runtime"]).toBe(
|
||||
aliasMap["@openclaw/plugin-sdk/media-runtime"],
|
||||
);
|
||||
expect(aliasMap["openclaw/plugin-sdk/provider-onboard"]).toBe(
|
||||
aliasMap["@openclaw/plugin-sdk/provider-onboard"],
|
||||
);
|
||||
expect(aliasMap["openclaw/plugin-sdk/speech-core"]).toBe(
|
||||
aliasMap["@openclaw/plugin-sdk/speech-core"],
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -53,7 +53,7 @@ const CAPABILITY_VITEST_SHIM_ALIASES = [
|
||||
},
|
||||
] as const;
|
||||
|
||||
export function buildVitestCapabilityShimAliasMap(): Record<string, string> {
|
||||
function buildVitestCapabilityShimAliasMap(): Record<string, string> {
|
||||
return Object.fromEntries(
|
||||
CAPABILITY_VITEST_SHIM_ALIASES.flatMap(({ subpath, target }) => {
|
||||
const targetPath = fileURLToPath(target);
|
||||
|
||||
@@ -6,7 +6,6 @@ import { afterEach, describe, expect, it } from "vitest";
|
||||
import {
|
||||
listBundledChannelPluginMetadata,
|
||||
resolveBundledChannelGeneratedPath,
|
||||
resolveBundledChannelWorkspacePath,
|
||||
} from "./bundled-channel-runtime.js";
|
||||
|
||||
const tempRoots: string[] = [];
|
||||
@@ -24,15 +23,6 @@ afterEach(() => {
|
||||
});
|
||||
|
||||
describe("bundled channel runtime metadata", () => {
|
||||
it("preserves explicit empty bundled roots", () => {
|
||||
const tempRoot = createTempRoot();
|
||||
|
||||
expect(listBundledChannelPluginMetadata({ rootDir: tempRoot })).toStrictEqual([]);
|
||||
expect(resolveBundledChannelWorkspacePath({ rootDir: tempRoot, pluginId: "telegram" })).toBe(
|
||||
null,
|
||||
);
|
||||
});
|
||||
|
||||
it("preserves explicit missing bundled scan roots", () => {
|
||||
const tempRoot = createTempRoot();
|
||||
const missingScanDir = path.join(tempRoot, "missing-extensions");
|
||||
|
||||
@@ -120,19 +120,3 @@ export function resolveBundledChannelGeneratedPath(
|
||||
): string | null {
|
||||
return resolveBundledPluginGeneratedPath(rootDir, entry, pluginDirName, scanDir);
|
||||
}
|
||||
|
||||
/** Resolves the source workspace path for a bundled channel plugin id. */
|
||||
export function resolveBundledChannelWorkspacePath(params: {
|
||||
rootDir: string;
|
||||
scanDir?: string;
|
||||
pluginId: string;
|
||||
}): string | null {
|
||||
return (
|
||||
listBundledChannelPluginMetadata({
|
||||
rootDir: params.rootDir,
|
||||
...(params.scanDir ? { scanDir: params.scanDir } : {}),
|
||||
includeChannelConfigs: false,
|
||||
includeSyntheticChannelConfigs: false,
|
||||
}).find((metadata) => metadata.manifest.id === params.pluginId)?.rootDir ?? null
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,11 +11,10 @@ import { resolveUserPath } from "../utils.js";
|
||||
|
||||
const DISABLED_BUNDLED_PLUGINS_DIR = path.join(os.tmpdir(), "openclaw-empty-bundled-plugins");
|
||||
const TEST_TRUST_BUNDLED_PLUGINS_DIR_ENV = "OPENCLAW_TEST_TRUST_BUNDLED_PLUGINS_DIR";
|
||||
let bundledPluginsDirOverrideForTest: string | undefined;
|
||||
const bundledPluginsDirCache = new Map<string, string | undefined>();
|
||||
|
||||
/** Diagnostic emitted when source-checkout bundled plugins lack dependency installs. */
|
||||
export type SourceCheckoutDependencyDiagnostic = {
|
||||
type SourceCheckoutDependencyDiagnostic = {
|
||||
source: string;
|
||||
message: string;
|
||||
};
|
||||
@@ -210,7 +209,6 @@ function createBundledPluginsDirCacheKey(env: NodeJS.ProcessEnv): string {
|
||||
openClawHome: env.OPENCLAW_HOME ?? "",
|
||||
home: env.HOME ?? "",
|
||||
userProfile: env.USERPROFILE ?? "",
|
||||
testOverride: bundledPluginsDirOverrideForTest ?? "",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -219,10 +217,6 @@ function resolveBundledPluginsDirUncached(env: NodeJS.ProcessEnv): string | unde
|
||||
return resolveDisabledBundledPluginsDir();
|
||||
}
|
||||
|
||||
if (bundledPluginsDirOverrideForTest) {
|
||||
return bundledPluginsDirOverrideForTest;
|
||||
}
|
||||
|
||||
const override = env.OPENCLAW_BUNDLED_PLUGINS_DIR?.trim();
|
||||
let rejectedExistingOverride: string | null = null;
|
||||
if (override) {
|
||||
@@ -309,11 +303,3 @@ export function resolveBundledPluginsDir(env: NodeJS.ProcessEnv = process.env):
|
||||
bundledPluginsDirCache.set(cacheKey, resolved);
|
||||
return resolved;
|
||||
}
|
||||
|
||||
export function setBundledPluginsDirOverrideForTest(dir: string | undefined): void {
|
||||
if (process.env.VITEST !== "true" && process.env.NODE_ENV !== "test") {
|
||||
throw new Error("setBundledPluginsDirOverrideForTest is only available in tests");
|
||||
}
|
||||
bundledPluginsDirOverrideForTest = dir;
|
||||
bundledPluginsDirCache.clear();
|
||||
}
|
||||
|
||||
@@ -3,23 +3,23 @@ import path from "node:path";
|
||||
import { isPathInside } from "./path-safety.js";
|
||||
|
||||
/** Alias class for current packaged paths and legacy bundled extension paths. */
|
||||
export type BundledPluginLoadPathAliasKind = "current" | "legacy";
|
||||
type BundledPluginLoadPathAliasKind = "current" | "legacy";
|
||||
|
||||
/** Load path alias used while resolving bundled plugins across package layouts. */
|
||||
export type BundledPluginLoadPathAlias = {
|
||||
type BundledPluginLoadPathAlias = {
|
||||
kind: BundledPluginLoadPathAliasKind;
|
||||
path: string;
|
||||
};
|
||||
|
||||
/** Parsed path metadata for a bundled plugin in a packaged dist root. */
|
||||
export type PackagedBundledPluginPath = {
|
||||
type PackagedBundledPluginPath = {
|
||||
packageRoot: string;
|
||||
bundledRoot: string;
|
||||
bundledLeaf: string;
|
||||
};
|
||||
|
||||
/** Parsed path metadata for a bundled plugin in the legacy extensions root. */
|
||||
export type LegacyBundledPluginPath = {
|
||||
type LegacyBundledPluginPath = {
|
||||
packageRoot: string;
|
||||
legacyRoot: string;
|
||||
bundledLeaf: string;
|
||||
|
||||
@@ -7,11 +7,12 @@ import { expectNoReaddirSyncDuring } from "../test-utils/fs-scan-assertions.js";
|
||||
import { listGitTrackedFiles, toRepoRelativePath } from "../test-utils/repo-files.js";
|
||||
import { collectBundledChannelConfigs } from "./bundled-channel-config-metadata.js";
|
||||
import {
|
||||
type BundledPluginMetadata,
|
||||
listBundledPluginMetadata,
|
||||
resolveBundledPluginGeneratedPath,
|
||||
resolveBundledPluginRepoEntryPath,
|
||||
} from "./bundled-plugin-metadata.js";
|
||||
|
||||
type BundledPluginMetadata = ReturnType<typeof listBundledPluginMetadata>[number];
|
||||
import { resolveGatewayStartupPluginIdsFromRegistry } from "./gateway-startup-plugin-ids.js";
|
||||
import {
|
||||
createGeneratedPluginTempRoot,
|
||||
|
||||
@@ -39,7 +39,7 @@ type BundledPluginPathPair = {
|
||||
};
|
||||
|
||||
/** Metadata collected from a bundled plugin package and manifest. */
|
||||
export type BundledPluginMetadata = {
|
||||
type BundledPluginMetadata = {
|
||||
dirName: string;
|
||||
idHint: string;
|
||||
source: BundledPluginPathPair;
|
||||
|
||||
@@ -8,7 +8,7 @@ import { resolveBundledPluginsDir } from "./bundled-dir.js";
|
||||
const DOCTOR_CONTRACT_BASENAMES = ["doctor-contract-api", "contract-api"] as const;
|
||||
const MODULE_EXTENSIONS = ["js", "cjs", "mjs", "ts", "cts", "mts"] as const;
|
||||
|
||||
export type BundledPluginStartupMetadata = {
|
||||
type BundledPluginStartupMetadata = {
|
||||
hasDoctorContract: boolean;
|
||||
};
|
||||
|
||||
|
||||
@@ -13,9 +13,7 @@ export type BundledPluginSource = {
|
||||
requiresConfig?: boolean;
|
||||
};
|
||||
|
||||
export type BundledPluginLookup =
|
||||
| { kind: "npmSpec"; value: string }
|
||||
| { kind: "pluginId"; value: string };
|
||||
type BundledPluginLookup = { kind: "npmSpec"; value: string } | { kind: "pluginId"; value: string };
|
||||
|
||||
export function findBundledPluginSourceInMap(params: {
|
||||
bundled: ReadonlyMap<string, BundledPluginSource>;
|
||||
|
||||
@@ -60,8 +60,7 @@ vi.mock("../infra/archive.js", async () => {
|
||||
const { ClawHubRequestError } = await import("../infra/clawhub.js");
|
||||
type ClawHubResolvedArtifact = import("../infra/clawhub.js").ClawHubResolvedArtifact;
|
||||
type ClawHubRiskAcknowledgementRequest = import("./clawhub.js").ClawHubRiskAcknowledgementRequest;
|
||||
const { CLAWHUB_INSTALL_ERROR_CODE, formatClawHubSpecifier, installPluginFromClawHub } =
|
||||
await import("./clawhub.js");
|
||||
const { CLAWHUB_INSTALL_ERROR_CODE, installPluginFromClawHub } = await import("./clawhub.js");
|
||||
|
||||
const DEMO_ARCHIVE_INTEGRITY = "sha256-qerEjGEpvES2+Tyan0j2xwDRkbcnmh4ZFfKN9vWbsa8=";
|
||||
const DEMO_ARCHIVE_SHA256 = "a9eac48c6129bc44b6f93c9a9f48f6c700d191b7279a1e1915f28df6f59bb1af";
|
||||
@@ -370,11 +369,6 @@ describe("installPluginFromClawHub", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("formats clawhub specifiers", () => {
|
||||
expect(formatClawHubSpecifier({ name: "demo" })).toBe("clawhub:demo");
|
||||
expect(formatClawHubSpecifier({ name: "demo", version: "1.2.3" })).toBe("clawhub:demo@1.2.3");
|
||||
});
|
||||
|
||||
it("installs a ClawHub plugin through the archive installer", async () => {
|
||||
const logger = createLoggerSpies();
|
||||
const result = await installPluginFromClawHub({
|
||||
|
||||
@@ -57,7 +57,7 @@ import {
|
||||
} from "./install.js";
|
||||
|
||||
export { CLAWHUB_INSTALL_ERROR_CODE };
|
||||
export type { ClawHubInstallErrorCode, ClawHubRiskAcknowledgementRequest };
|
||||
export type { ClawHubRiskAcknowledgementRequest };
|
||||
|
||||
type PluginInstallLogger = {
|
||||
info?: (message: string) => void;
|
||||
@@ -331,7 +331,7 @@ function resolveTopLevelLegacyArchiveVerification(
|
||||
return integrity ? { kind: "archive-integrity", integrity } : null;
|
||||
}
|
||||
|
||||
export function formatClawHubSpecifier(params: { name: string; version?: string }): string {
|
||||
function formatClawHubSpecifier(params: { name: string; version?: string }): string {
|
||||
return `clawhub:${params.name}${params.version ? `@${params.version}` : ""}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ export type CliBackendThinkingLevel =
|
||||
export type CliBackendExecutionMode = "agent" | "side-question";
|
||||
|
||||
/** Host-isolated tool grant for a CLI run with every native tool disabled. */
|
||||
export type CliBackendToolAvailability = {
|
||||
type CliBackendToolAvailability = {
|
||||
native: readonly [];
|
||||
/** MCP tools already isolated by the host transport that may be auto-approved. */
|
||||
mcp: readonly string[];
|
||||
|
||||
@@ -3,7 +3,7 @@ import { getActiveRuntimePluginRegistry } from "./active-runtime-registry.js";
|
||||
import type { CliBackendPlugin } from "./cli-backend.types.js";
|
||||
|
||||
/** Runtime CLI backend registration with owning plugin id. */
|
||||
export type PluginCliBackendEntry = CliBackendPlugin & {
|
||||
type PluginCliBackendEntry = CliBackendPlugin & {
|
||||
pluginId: string;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
/** Tests plugin CLI node Gateway runtime timeout and invocation behavior. */
|
||||
import { MAX_TIMER_TIMEOUT_MS } from "@openclaw/normalization-core/number-coercion";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
createPluginCliGatewayNodesRuntime,
|
||||
resolvePluginCliNodeInvokeGatewayTimeoutMs,
|
||||
} from "./cli-gateway-nodes-runtime.js";
|
||||
import { createPluginCliGatewayNodesRuntime } from "./cli-gateway-nodes-runtime.js";
|
||||
import { withPluginRuntimePluginScope } from "./runtime/gateway-request-scope.js";
|
||||
|
||||
const callGatewayMock = vi.fn();
|
||||
@@ -76,15 +73,3 @@ describe("createPluginCliGatewayNodesRuntime", () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolvePluginCliNodeInvokeGatewayTimeoutMs", () => {
|
||||
it("preserves absent and non-positive timeout behavior", () => {
|
||||
expect(resolvePluginCliNodeInvokeGatewayTimeoutMs(undefined)).toBeUndefined();
|
||||
expect(resolvePluginCliNodeInvokeGatewayTimeoutMs(0)).toBeUndefined();
|
||||
expect(resolvePluginCliNodeInvokeGatewayTimeoutMs(-1)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("adds gateway grace for normal positive timeouts", () => {
|
||||
expect(resolvePluginCliNodeInvokeGatewayTimeoutMs(10_000)).toBe(15_000);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ import { getPluginRuntimeGatewayRequestScope } from "./runtime/gateway-request-s
|
||||
import type { PluginRuntime } from "./runtime/types.js";
|
||||
|
||||
/** Adds Gateway timer grace for plugin CLI node invoke calls. */
|
||||
export function resolvePluginCliNodeInvokeGatewayTimeoutMs(
|
||||
function resolvePluginCliNodeInvokeGatewayTimeoutMs(
|
||||
timeoutMs: number | undefined,
|
||||
): number | undefined {
|
||||
return typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0
|
||||
|
||||
@@ -3,7 +3,7 @@ import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createBundledBrowserPluginFixture } from "../../test/helpers/browser-bundled-plugin-fixture.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { clearPluginLoaderCache, loadOpenClawPlugins } from "./loader.js";
|
||||
import { clearPluginLoaderCache, loadOpenClawPlugins } from "./loader.test-fixtures.js";
|
||||
import { resetPluginRuntimeStateForTest } from "./runtime.js";
|
||||
|
||||
function resetPluginState() {
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
clearPluginCommandsForPlugin,
|
||||
isPluginCommandRegistryLocked,
|
||||
pluginCommands,
|
||||
type RegisteredPluginCommand,
|
||||
} from "./command-registry-state.js";
|
||||
import {
|
||||
AGENT_PROMPT_SURFACE_KINDS,
|
||||
@@ -79,7 +78,7 @@ function getAgentPromptSurfaces(): Set<string> {
|
||||
}
|
||||
|
||||
/** Result returned when a plugin command registration succeeds or fails validation. */
|
||||
export type CommandRegistrationResult = {
|
||||
type CommandRegistrationResult = {
|
||||
ok: boolean;
|
||||
error?: string;
|
||||
};
|
||||
@@ -388,4 +387,3 @@ export function registerPluginCommand(
|
||||
}
|
||||
|
||||
export { clearPluginCommands, clearPluginCommandsForPlugin };
|
||||
export type { RegisteredPluginCommand };
|
||||
|
||||
@@ -15,7 +15,7 @@ type PluginCommandSpecOptions = {
|
||||
config?: OpenClawConfig;
|
||||
};
|
||||
|
||||
export type PluginCommandEntrySpec = {
|
||||
type PluginCommandEntrySpec = {
|
||||
name: string;
|
||||
description: string;
|
||||
acceptsArgs: boolean;
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
import { createPluginRegistry } from "./registry.js";
|
||||
import { setActivePluginRegistry } from "./runtime.js";
|
||||
import type { PluginRuntime } from "./runtime/types.js";
|
||||
import { createBundledPluginRecord } from "./status.test-helpers.js";
|
||||
import { createBundledPluginRecord } from "./status.test-fixtures.js";
|
||||
|
||||
const completionMocks = vi.hoisted(() => ({
|
||||
prepareSimpleCompletionModelForAgent: vi.fn(),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user