# frozen_string_literal: true require 'json' require 'fileutils' require_relative '../file_locations' require_relative '../file_verifier' module PluginConfig module Operations class Base attr_reader :plugin, :marketplace, :project, :marketplace_file def initialize(params) @plugin = params[:plugin] @marketplace = params[:marketplace] @project = params[:project] @marketplace_file = params[:marketplace_file] end private def plugin_key "#{plugin}@#{resolved_marketplace}" end # The marketplace id this plugin is actually installed under, per # installed_plugins.json, falling back to the --marketplace param when # no installed entry exists yet (e.g. before first install). Needed # because cc-os's os-* plugins install under a `local-plugins` # marketplace (symlink into ~/.claude/plugins) rather than whatever # marketplace id the caller assumes (e.g. the repo's own `cc-os`), # which otherwise produces false "not installed" results. def resolved_marketplace data = read_json(installed_plugins_path) if data && data['plugins'] match = data['plugins'].keys.find { |k| k.start_with?("#{plugin}@") } return match.split('@', 2).last if match end marketplace end def read_json(path) return nil unless File.exist?(path) JSON.parse(File.read(path)) rescue JSON::ParserError nil end def write_json(path, data) FileUtils.mkdir_p(File.dirname(path)) content = JSON.pretty_generate(data, indent: ' ') + "\n" File.write(path, content) verifier = FileVerifier.new(path) verifier.verify_written(content) end def settings_path File.join(project, '.claude', 'settings.json') end def installed_plugins_path File.join(Dir.home, '.claude', 'plugins', 'installed_plugins.json') end end end end