init claude-code
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
import 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'>
|
||||
}
|
||||
Reference in New Issue
Block a user