diff --git a/packages/agents/src/__tests__/adapters.test.ts b/packages/agents/src/__tests__/adapters.test.ts index 4bba8621..8e6c10dc 100644 --- a/packages/agents/src/__tests__/adapters.test.ts +++ b/packages/agents/src/__tests__/adapters.test.ts @@ -35,10 +35,10 @@ const ALL_AGENTS = AgentType.options; describe('Agent Adapters', () => { describe('getAllAdapters', () => { - it('should return all 44 registered adapters', () => { + it('should return all 45 registered adapters', () => { const adapters = getAllAdapters(); expect(adapters).toBeInstanceOf(Array); - expect(adapters.length).toBe(44); + expect(adapters.length).toBe(45); }); it('should include common agents', () => { diff --git a/packages/agents/src/__tests__/clawdbot.test.ts b/packages/agents/src/__tests__/clawdbot.test.ts index 28017bf5..59fcae40 100644 --- a/packages/agents/src/__tests__/clawdbot.test.ts +++ b/packages/agents/src/__tests__/clawdbot.test.ts @@ -236,16 +236,6 @@ describe('ClawdbotAdapter', () => { }); describe('isDetected', () => { - it('should detect Clawdbot from workspace skills directory', async () => { - mockExistsSync.mockImplementation((path) => { - return path === join(process.cwd(), 'skills'); - }); - - const detected = await adapter.isDetected(); - - expect(detected).toBe(true); - }); - it('should detect Clawdbot from global directory', async () => { mockExistsSync.mockImplementation((path) => { return path === join(homedir(), '.clawdbot'); @@ -287,7 +277,6 @@ describe('ClawdbotAdapter', () => { await adapter.isDetected(); - expect(mockExistsSync).toHaveBeenCalledWith(join(process.cwd(), 'skills')); expect(mockExistsSync).toHaveBeenCalledWith(join(homedir(), '.clawdbot')); expect(mockExistsSync).toHaveBeenCalledWith(join(process.cwd(), 'clawdbot.json')); }); diff --git a/packages/agents/src/clawdbot.ts b/packages/agents/src/clawdbot.ts index 2f56a339..d5675be7 100644 --- a/packages/agents/src/clawdbot.ts +++ b/packages/agents/src/clawdbot.ts @@ -10,9 +10,9 @@ const config = AGENT_CONFIG.clawdbot; export class ClawdbotAdapter implements AgentAdapter { readonly type: AgentType = 'clawdbot'; - readonly name = 'Clawdbot'; - readonly skillsDir = config.skillsDir; - readonly configFile = config.configFile; + readonly name: string = 'Clawdbot'; + readonly skillsDir: string = config.skillsDir; + readonly configFile: string = config.configFile; generateConfig(skills: Skill[]): string { const enabledSkills = skills.filter(s => s.enabled); @@ -69,10 +69,9 @@ ${skillsXml} } async isDetected(): Promise { - const projectSkills = join(process.cwd(), 'skills'); const globalClawdbot = join(homedir(), '.clawdbot'); const clawdbotConfig = join(process.cwd(), 'clawdbot.json'); - return existsSync(projectSkills) || existsSync(globalClawdbot) || existsSync(clawdbotConfig); + return existsSync(globalClawdbot) || existsSync(clawdbotConfig); } } diff --git a/packages/agents/src/index.ts b/packages/agents/src/index.ts index fcf1879e..d1ab1c84 100644 --- a/packages/agents/src/index.ts +++ b/packages/agents/src/index.ts @@ -8,6 +8,7 @@ import { OpenCodeAdapter } from './opencode.js'; import { AntigravityAdapter } from './antigravity.js'; import { AmpAdapter } from './amp.js'; import { ClawdbotAdapter } from './clawdbot.js'; +import { OpenClawAdapter } from './openclaw.js'; import { DroidAdapter } from './droid.js'; import { FactoryAdapter } from './factory.js'; import { GitHubCopilotAdapter } from './github-copilot.js'; @@ -29,6 +30,7 @@ export * from './opencode.js'; export * from './antigravity.js'; export * from './amp.js'; export * from './clawdbot.js'; +export * from './openclaw.js'; export * from './droid.js'; export * from './factory.js'; export * from './github-copilot.js'; @@ -53,6 +55,7 @@ const adapters: Record = { antigravity: new AntigravityAdapter(), amp: new AmpAdapter(), clawdbot: new ClawdbotAdapter(), + openclaw: new OpenClawAdapter(), droid: new DroidAdapter(), 'github-copilot': new GitHubCopilotAdapter(), goose: new GooseAdapter(), @@ -120,6 +123,7 @@ export async function detectAgent(): Promise { 'opencode', 'antigravity', 'amp', + 'openclaw', 'clawdbot', 'droid', 'github-copilot', diff --git a/packages/agents/src/openclaw.ts b/packages/agents/src/openclaw.ts new file mode 100644 index 00000000..b8ee7d8f --- /dev/null +++ b/packages/agents/src/openclaw.ts @@ -0,0 +1,22 @@ +import { existsSync } from 'node:fs'; +import { join } from 'node:path'; +import { homedir } from 'node:os'; +import { ClawdbotAdapter } from './clawdbot.js'; +import type { AgentType } from '@skillkit/core'; +import { AGENT_CONFIG } from '@skillkit/core'; + +const config = AGENT_CONFIG.openclaw; + +export class OpenClawAdapter extends ClawdbotAdapter { + override readonly type: AgentType = 'openclaw'; + override readonly name = 'OpenClaw'; + override readonly skillsDir = config.skillsDir; + override readonly configFile = config.configFile; + + override async isDetected(): Promise { + const globalOpenClaw = join(homedir(), '.openclaw'); + const openclawConfig = join(process.cwd(), 'openclaw.json'); + + return existsSync(globalOpenClaw) || existsSync(openclawConfig); + } +} diff --git a/packages/core/src/agent-config.ts b/packages/core/src/agent-config.ts index cfe4f772..4c5e7fe5 100644 --- a/packages/core/src/agent-config.ts +++ b/packages/core/src/agent-config.ts @@ -111,16 +111,29 @@ export const AGENT_CONFIG: Record = { supportsAutoDiscovery: true, }, - // Clawdbot clawdbot: { skillsDir: '.clawdbot/skills', configFile: 'AGENTS.md', - altSkillsDirs: ['skills'], + altSkillsDirs: ['skills', '~/.clawdbot/skills'], configFormat: 'xml', usesFrontmatter: true, supportsAutoDiscovery: true, }, + openclaw: { + skillsDir: 'skills', + configFile: 'CLAUDE.md', + altSkillsDirs: ['~/.openclaw/skills'], + globalSkillsDir: '~/.openclaw/skills', + configFormat: 'xml', + usesFrontmatter: true, + frontmatterFields: [ + 'name', 'description', 'version', 'scan_exempt', + 'permissions', 'triggers', 'metadata', + ], + supportsAutoDiscovery: true, + }, + // Droid (Factory) droid: { skillsDir: '.factory/skills', diff --git a/packages/core/src/agents/types.ts b/packages/core/src/agents/types.ts index beaacb92..f7ea4a65 100644 --- a/packages/core/src/agents/types.ts +++ b/packages/core/src/agents/types.ts @@ -227,6 +227,7 @@ export const AGENT_DISCOVERY_PATHS: Record = { 'antigravity': ['.antigravity/agents'], 'amp': ['.amp/agents'], 'clawdbot': ['.clawdbot/agents', 'agents'], + 'openclaw': ['agents', '.openclaw/agents'], 'droid': ['.droid/agents'], 'github-copilot': ['.github/agents', '.github/instructions', '.github/custom-agents'], 'goose': ['.goose/agents'], @@ -277,6 +278,7 @@ export const ALL_AGENT_DISCOVERY_PATHS = [ '.cline/agents', '.clawdbot/agents', '.codebuddy/agents', + '.openclaw/agents', '.codex/agents', '.commandcode/agents', '.continue/agents', @@ -336,6 +338,7 @@ export const CUSTOM_AGENT_FORMAT_MAP: Record = { 'antigravity': 'claude-agent', 'amp': 'claude-agent', 'clawdbot': 'claude-agent', + 'openclaw': 'claude-agent', 'droid': 'claude-agent', 'github-copilot': 'universal', 'goose': 'claude-agent', diff --git a/packages/core/src/commands/generator.ts b/packages/core/src/commands/generator.ts index 932d314d..f2f01e21 100644 --- a/packages/core/src/commands/generator.ts +++ b/packages/core/src/commands/generator.ts @@ -73,6 +73,13 @@ const AGENT_FORMATS: Record = { supportsSlashCommands: true, supportsCommandFiles: true, }, + openclaw: { + agent: 'openclaw', + extension: '.md', + directory: '.claude/commands', + supportsSlashCommands: true, + supportsCommandFiles: true, + }, droid: { agent: 'droid', extension: '.md', diff --git a/packages/core/src/translator/types.ts b/packages/core/src/translator/types.ts index 1d6bd7b1..02c4418a 100644 --- a/packages/core/src/translator/types.ts +++ b/packages/core/src/translator/types.ts @@ -21,6 +21,7 @@ export const AGENT_FORMAT_MAP: Record = { 'antigravity': 'skill-md', 'amp': 'skill-md', 'clawdbot': 'skill-md', + 'openclaw': 'skill-md', 'droid': 'skill-md', 'goose': 'skill-md', 'kilo': 'skill-md', diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 7ae424d4..d5c04586 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -9,6 +9,7 @@ export const AgentType = z.enum([ "gemini-cli", "amp", "clawdbot", + "openclaw", "droid", "github-copilot", "goose",