chore: initialize recovered claude workspace
This commit is contained in:
159
src/plugins/builtinPlugins.ts
Normal file
159
src/plugins/builtinPlugins.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* Built-in Plugin Registry
|
||||
*
|
||||
* Manages built-in plugins that ship with the CLI and can be enabled/disabled
|
||||
* by users via the /plugin UI.
|
||||
*
|
||||
* Built-in plugins differ from bundled skills (src/skills/bundled/) in that:
|
||||
* - They appear in the /plugin UI under a "Built-in" section
|
||||
* - Users can enable/disable them (persisted to user settings)
|
||||
* - They can provide multiple components (skills, hooks, MCP servers)
|
||||
*
|
||||
* Plugin IDs use the format `{name}@builtin` to distinguish them from
|
||||
* marketplace plugins (`{name}@{marketplace}`).
|
||||
*/
|
||||
|
||||
import type { Command } from '../commands.js'
|
||||
import type { BundledSkillDefinition } from '../skills/bundledSkills.js'
|
||||
import type { BuiltinPluginDefinition, LoadedPlugin } from '../types/plugin.js'
|
||||
import { getSettings_DEPRECATED } from '../utils/settings/settings.js'
|
||||
|
||||
const BUILTIN_PLUGINS: Map<string, BuiltinPluginDefinition> = new Map()
|
||||
|
||||
export const BUILTIN_MARKETPLACE_NAME = 'builtin'
|
||||
|
||||
/**
|
||||
* Register a built-in plugin. Call this from initBuiltinPlugins() at startup.
|
||||
*/
|
||||
export function registerBuiltinPlugin(
|
||||
definition: BuiltinPluginDefinition,
|
||||
): void {
|
||||
BUILTIN_PLUGINS.set(definition.name, definition)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a plugin ID represents a built-in plugin (ends with @builtin).
|
||||
*/
|
||||
export function isBuiltinPluginId(pluginId: string): boolean {
|
||||
return pluginId.endsWith(`@${BUILTIN_MARKETPLACE_NAME}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific built-in plugin definition by name.
|
||||
* Useful for the /plugin UI to show the skills/hooks/MCP list without
|
||||
* a marketplace lookup.
|
||||
*/
|
||||
export function getBuiltinPluginDefinition(
|
||||
name: string,
|
||||
): BuiltinPluginDefinition | undefined {
|
||||
return BUILTIN_PLUGINS.get(name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all registered built-in plugins as LoadedPlugin objects, split into
|
||||
* enabled/disabled based on user settings (with defaultEnabled as fallback).
|
||||
* Plugins whose isAvailable() returns false are omitted entirely.
|
||||
*/
|
||||
export function getBuiltinPlugins(): {
|
||||
enabled: LoadedPlugin[]
|
||||
disabled: LoadedPlugin[]
|
||||
} {
|
||||
const settings = getSettings_DEPRECATED()
|
||||
const enabled: LoadedPlugin[] = []
|
||||
const disabled: LoadedPlugin[] = []
|
||||
|
||||
for (const [name, definition] of BUILTIN_PLUGINS) {
|
||||
if (definition.isAvailable && !definition.isAvailable()) {
|
||||
continue
|
||||
}
|
||||
|
||||
const pluginId = `${name}@${BUILTIN_MARKETPLACE_NAME}`
|
||||
const userSetting = settings?.enabledPlugins?.[pluginId]
|
||||
// Enabled state: user preference > plugin default > true
|
||||
const isEnabled =
|
||||
userSetting !== undefined
|
||||
? userSetting === true
|
||||
: (definition.defaultEnabled ?? true)
|
||||
|
||||
const plugin: LoadedPlugin = {
|
||||
name,
|
||||
manifest: {
|
||||
name,
|
||||
description: definition.description,
|
||||
version: definition.version,
|
||||
},
|
||||
path: BUILTIN_MARKETPLACE_NAME, // sentinel — no filesystem path
|
||||
source: pluginId,
|
||||
repository: pluginId,
|
||||
enabled: isEnabled,
|
||||
isBuiltin: true,
|
||||
hooksConfig: definition.hooks,
|
||||
mcpServers: definition.mcpServers,
|
||||
}
|
||||
|
||||
if (isEnabled) {
|
||||
enabled.push(plugin)
|
||||
} else {
|
||||
disabled.push(plugin)
|
||||
}
|
||||
}
|
||||
|
||||
return { enabled, disabled }
|
||||
}
|
||||
|
||||
/**
|
||||
* Get skills from enabled built-in plugins as Command objects.
|
||||
* Skills from disabled plugins are not returned.
|
||||
*/
|
||||
export function getBuiltinPluginSkillCommands(): Command[] {
|
||||
const { enabled } = getBuiltinPlugins()
|
||||
const commands: Command[] = []
|
||||
|
||||
for (const plugin of enabled) {
|
||||
const definition = BUILTIN_PLUGINS.get(plugin.name)
|
||||
if (!definition?.skills) continue
|
||||
for (const skill of definition.skills) {
|
||||
commands.push(skillDefinitionToCommand(skill))
|
||||
}
|
||||
}
|
||||
|
||||
return commands
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear built-in plugins registry (for testing).
|
||||
*/
|
||||
export function clearBuiltinPlugins(): void {
|
||||
BUILTIN_PLUGINS.clear()
|
||||
}
|
||||
|
||||
// --
|
||||
|
||||
function skillDefinitionToCommand(definition: BundledSkillDefinition): Command {
|
||||
return {
|
||||
type: 'prompt',
|
||||
name: definition.name,
|
||||
description: definition.description,
|
||||
hasUserSpecifiedDescription: true,
|
||||
allowedTools: definition.allowedTools ?? [],
|
||||
argumentHint: definition.argumentHint,
|
||||
whenToUse: definition.whenToUse,
|
||||
model: definition.model,
|
||||
disableModelInvocation: definition.disableModelInvocation ?? false,
|
||||
userInvocable: definition.userInvocable ?? true,
|
||||
contentLength: 0,
|
||||
// 'bundled' not 'builtin' — 'builtin' in Command.source means hardcoded
|
||||
// slash commands (/help, /clear). Using 'bundled' keeps these skills in
|
||||
// the Skill tool's listing, analytics name logging, and prompt-truncation
|
||||
// exemption. The user-toggleable aspect is tracked on LoadedPlugin.isBuiltin.
|
||||
source: 'bundled',
|
||||
loadedFrom: 'bundled',
|
||||
hooks: definition.hooks,
|
||||
context: definition.context,
|
||||
agent: definition.agent,
|
||||
isEnabled: definition.isEnabled ?? (() => true),
|
||||
isHidden: !(definition.userInvocable ?? true),
|
||||
progressMessage: 'running',
|
||||
getPromptForCommand: definition.getPromptForCommand,
|
||||
}
|
||||
}
|
||||
23
src/plugins/bundled/index.ts
Normal file
23
src/plugins/bundled/index.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Built-in Plugin Initialization
|
||||
*
|
||||
* Initializes built-in plugins that ship with the CLI and appear in the
|
||||
* /plugin UI for users to enable/disable.
|
||||
*
|
||||
* Not all bundled features should be built-in plugins — use this for
|
||||
* features that users should be able to explicitly enable/disable. For
|
||||
* features with complex setup or automatic-enabling logic (e.g.
|
||||
* claude-in-chrome), use src/skills/bundled/ instead.
|
||||
*
|
||||
* To add a new built-in plugin:
|
||||
* 1. Import registerBuiltinPlugin from '../builtinPlugins.js'
|
||||
* 2. Call registerBuiltinPlugin() with the plugin definition here
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize built-in plugins. Called during CLI startup.
|
||||
*/
|
||||
export function initBuiltinPlugins(): void {
|
||||
// No built-in plugins registered yet — this is the scaffolding for
|
||||
// migrating bundled skills that should be user-toggleable.
|
||||
}
|
||||
Reference in New Issue
Block a user