Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
3.9 kB · 123 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124import type { EditableSettingSource, SettingSource,} from '../settings/constants.js'import { ALLOWED_OFFICIAL_MARKETPLACE_NAMES, type PluginScope,} from './schemas.js'
/** * Extended scope type that includes 'flag' for session-only plugins. * 'flag' scope is NOT persisted to installed_plugins.json. */export type ExtendedPluginScope = PluginScope | 'flag'
/** * Scopes that are persisted to installed_plugins.json. * Excludes 'flag' which is session-only. */export type PersistablePluginScope = Exclude<ExtendedPluginScope, 'flag'>
/** * Map from SettingSource to plugin scope. * Note: flagSettings maps to 'flag' which is session-only and not persisted. */export const SETTING_SOURCE_TO_SCOPE = { policySettings: 'managed', userSettings: 'user', projectSettings: 'project', localSettings: 'local', flagSettings: 'flag',} as const satisfies Record<SettingSource, ExtendedPluginScope>
/** * Parsed plugin identifier with name and optional marketplace */export type ParsedPluginIdentifier = { name: string marketplace?: string}
/** * Parse a plugin identifier string into name and marketplace components * @param plugin The plugin identifier (name or name@marketplace) * @returns Parsed plugin name and optional marketplace * * Note: Only the first '@' is used as separator. If the input contains multiple '@' symbols * (e.g., "plugin@market@place"), everything after the second '@' is ignored. * This is intentional as marketplace names should not contain '@'. */export function parsePluginIdentifier(plugin: string): ParsedPluginIdentifier { if (plugin.includes('@')) { const parts = plugin.split('@') return { name: parts[0] || '', marketplace: parts[1] } } return { name: plugin }}
/** * Build a plugin ID from name and marketplace * @param name The plugin name * @param marketplace Optional marketplace name * @returns Plugin ID in format "name" or "name@marketplace" */export function buildPluginId(name: string, marketplace?: string): string { return marketplace ? `${name}@${marketplace}` : name}
/** * Check if a marketplace name is an official (Anthropic-controlled) marketplace. * Used for telemetry redaction — official plugin identifiers are safe to log to * general-access additional_metadata; third-party identifiers go only to the * PII-tagged _PROTO_* BQ columns. */export function isOfficialMarketplaceName( marketplace: string | undefined,): boolean { return ( marketplace !== undefined && ALLOWED_OFFICIAL_MARKETPLACE_NAMES.has(marketplace.toLowerCase()) )}
/** * Map from installable plugin scope to editable setting source. * This is the inverse of SETTING_SOURCE_TO_SCOPE for editable scopes only. * Note: 'managed' scope cannot be installed to, so it's not included here. */const SCOPE_TO_EDITABLE_SOURCE: Record< Exclude<PluginScope, 'managed'>, EditableSettingSource> = { user: 'userSettings', project: 'projectSettings', local: 'localSettings',}
/** * Convert a plugin scope to its corresponding editable setting source * @param scope The plugin installation scope * @returns The corresponding setting source for reading/writing settings * @throws Error if scope is 'managed' (cannot install plugins to managed scope) */export function scopeToSettingSource( scope: PluginScope,): EditableSettingSource { if (scope === 'managed') { throw new Error('Cannot install plugins to managed scope') } return SCOPE_TO_EDITABLE_SOURCE[scope]}
/** * Convert an editable setting source to its corresponding plugin scope. * Derived from SETTING_SOURCE_TO_SCOPE to maintain a single source of truth. * @param source The setting source * @returns The corresponding plugin scope */export function settingSourceToScope( source: EditableSettingSource,): Exclude<PluginScope, 'managed'> { return SETTING_SOURCE_TO_SCOPE[source] as Exclude<PluginScope, 'managed'>}